mirror of
https://github.com/sipeed/Maixduino.git
synced 2026-03-03 00:53:59 +01:00
remove sdk
This commit is contained in:
814
cores/arduino/kendryte-standalone-sdk/.gitignore
vendored
814
cores/arduino/kendryte-standalone-sdk/.gitignore
vendored
@@ -1,814 +0,0 @@
|
||||
# File created using '.gitignore Generator' for Visual Studio Code: https://bit.ly/vscode-gig
|
||||
|
||||
# Created by https://www.gitignore.io/api/visualstudiocode,windows,c,c++,cmake,codeblocks,intellij+all,jetbrains+all,kdevelop4,linux,macos,osx,pycharm+all,vim,visualstudio,xcode
|
||||
# Edit at https://www.gitignore.io/?templates=visualstudiocode,windows,c,c++,cmake,codeblocks,intellij+all,jetbrains+all,kdevelop4,linux,macos,osx,pycharm+all,vim,visualstudio,xcode
|
||||
|
||||
### C ###
|
||||
# Prerequisites
|
||||
*.d
|
||||
|
||||
# Object files
|
||||
*.o
|
||||
*.ko
|
||||
*.obj
|
||||
*.elf
|
||||
|
||||
# Linker output
|
||||
*.ilk
|
||||
*.map
|
||||
*.exp
|
||||
|
||||
# Precompiled Headers
|
||||
*.gch
|
||||
*.pch
|
||||
|
||||
# Libraries
|
||||
*.lib
|
||||
*.a
|
||||
*.la
|
||||
*.lo
|
||||
|
||||
# Shared objects (inc. Windows DLLs)
|
||||
*.dll
|
||||
*.so
|
||||
*.so.*
|
||||
*.dylib
|
||||
|
||||
# Executables
|
||||
*.exe
|
||||
*.out
|
||||
*.app
|
||||
*.i*86
|
||||
*.x86_64
|
||||
*.hex
|
||||
|
||||
# Debug files
|
||||
*.dSYM/
|
||||
*.su
|
||||
*.idb
|
||||
*.pdb
|
||||
|
||||
# Kernel Module Compile Results
|
||||
*.mod*
|
||||
*.cmd
|
||||
.tmp_versions/
|
||||
modules.order
|
||||
Module.symvers
|
||||
Mkfile.old
|
||||
dkms.conf
|
||||
|
||||
### C++ ###
|
||||
# Prerequisites
|
||||
|
||||
# Compiled Object files
|
||||
*.slo
|
||||
|
||||
# Precompiled Headers
|
||||
|
||||
# Compiled Dynamic libraries
|
||||
|
||||
# Fortran module files
|
||||
*.mod
|
||||
*.smod
|
||||
|
||||
# Compiled Static libraries
|
||||
*.lai
|
||||
|
||||
# Executables
|
||||
|
||||
### CMake ###
|
||||
CMakeCache.txt
|
||||
CMakeFiles
|
||||
CMakeScripts
|
||||
Testing
|
||||
Makefile
|
||||
cmake_install.cmake
|
||||
install_manifest.txt
|
||||
compile_commands.json
|
||||
CTestTestfile.cmake
|
||||
|
||||
### CodeBlocks ###
|
||||
# specific to CodeBlocks IDE
|
||||
*.layout
|
||||
*.depend
|
||||
*.cbp
|
||||
# generated directories
|
||||
bin/
|
||||
obj/
|
||||
|
||||
### Intellij+all ###
|
||||
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm
|
||||
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
|
||||
|
||||
# User-specific stuff
|
||||
.idea/**/workspace.xml
|
||||
.idea/**/tasks.xml
|
||||
.idea/**/usage.statistics.xml
|
||||
.idea/**/dictionaries
|
||||
.idea/**/shelf
|
||||
|
||||
# Generated files
|
||||
.idea/**/contentModel.xml
|
||||
|
||||
# Sensitive or high-churn files
|
||||
.idea/**/dataSources/
|
||||
.idea/**/dataSources.ids
|
||||
.idea/**/dataSources.local.xml
|
||||
.idea/**/sqlDataSources.xml
|
||||
.idea/**/dynamic.xml
|
||||
.idea/**/uiDesigner.xml
|
||||
.idea/**/dbnavigator.xml
|
||||
|
||||
# Gradle
|
||||
.idea/**/gradle.xml
|
||||
.idea/**/libraries
|
||||
|
||||
# Gradle and Maven with auto-import
|
||||
# When using Gradle or Maven with auto-import, you should exclude module files,
|
||||
# since they will be recreated, and may cause churn. Uncomment if using
|
||||
# auto-import.
|
||||
# .idea/modules.xml
|
||||
# .idea/*.iml
|
||||
# .idea/modules
|
||||
|
||||
# CMake
|
||||
cmake-build-*/
|
||||
|
||||
# Mongo Explorer plugin
|
||||
.idea/**/mongoSettings.xml
|
||||
|
||||
# File-based project format
|
||||
*.iws
|
||||
|
||||
# IntelliJ
|
||||
out/
|
||||
|
||||
# mpeltonen/sbt-idea plugin
|
||||
.idea_modules/
|
||||
|
||||
# JIRA plugin
|
||||
atlassian-ide-plugin.xml
|
||||
|
||||
# Cursive Clojure plugin
|
||||
.idea/replstate.xml
|
||||
|
||||
# Crashlytics plugin (for Android Studio and IntelliJ)
|
||||
com_crashlytics_export_strings.xml
|
||||
crashlytics.properties
|
||||
crashlytics-build.properties
|
||||
fabric.properties
|
||||
|
||||
# Editor-based Rest Client
|
||||
.idea/httpRequests
|
||||
|
||||
# Android studio 3.1+ serialized cache file
|
||||
.idea/caches/build_file_checksums.ser
|
||||
|
||||
### Intellij+all Patch ###
|
||||
# Ignores the whole .idea folder and all .iml files
|
||||
# See https://github.com/joeblau/gitignore.io/issues/186 and https://github.com/joeblau/gitignore.io/issues/360
|
||||
|
||||
.idea/
|
||||
|
||||
# Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-249601023
|
||||
|
||||
*.iml
|
||||
modules.xml
|
||||
.idea/misc.xml
|
||||
*.ipr
|
||||
|
||||
### JetBrains+all ###
|
||||
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm
|
||||
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
|
||||
|
||||
# User-specific stuff
|
||||
|
||||
# Generated files
|
||||
|
||||
# Sensitive or high-churn files
|
||||
|
||||
# Gradle
|
||||
|
||||
# Gradle and Maven with auto-import
|
||||
# When using Gradle or Maven with auto-import, you should exclude module files,
|
||||
# since they will be recreated, and may cause churn. Uncomment if using
|
||||
# auto-import.
|
||||
# .idea/modules.xml
|
||||
# .idea/*.iml
|
||||
# .idea/modules
|
||||
|
||||
# CMake
|
||||
|
||||
# Mongo Explorer plugin
|
||||
|
||||
# File-based project format
|
||||
|
||||
# IntelliJ
|
||||
|
||||
# mpeltonen/sbt-idea plugin
|
||||
|
||||
# JIRA plugin
|
||||
|
||||
# Cursive Clojure plugin
|
||||
|
||||
# Crashlytics plugin (for Android Studio and IntelliJ)
|
||||
|
||||
# Editor-based Rest Client
|
||||
|
||||
# Android studio 3.1+ serialized cache file
|
||||
|
||||
### JetBrains+all Patch ###
|
||||
# Ignores the whole .idea folder and all .iml files
|
||||
# See https://github.com/joeblau/gitignore.io/issues/186 and https://github.com/joeblau/gitignore.io/issues/360
|
||||
|
||||
|
||||
# Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-249601023
|
||||
|
||||
|
||||
### KDevelop4 ###
|
||||
*.kdev4
|
||||
.kdev4/
|
||||
|
||||
### Linux ###
|
||||
*~
|
||||
|
||||
# temporary files which can be created if a process still has a handle open of a deleted file
|
||||
.fuse_hidden*
|
||||
|
||||
# KDE directory preferences
|
||||
.directory
|
||||
|
||||
# Linux trash folder which might appear on any partition or disk
|
||||
.Trash-*
|
||||
|
||||
# .nfs files are created when an open file is removed but is still being accessed
|
||||
.nfs*
|
||||
|
||||
### macOS ###
|
||||
# General
|
||||
.DS_Store
|
||||
.AppleDouble
|
||||
.LSOverride
|
||||
|
||||
# Icon must end with two \r
|
||||
Icon
|
||||
|
||||
# Thumbnails
|
||||
._*
|
||||
|
||||
# Files that might appear in the root of a volume
|
||||
.DocumentRevisions-V100
|
||||
.fseventsd
|
||||
.Spotlight-V100
|
||||
.TemporaryItems
|
||||
.Trashes
|
||||
.VolumeIcon.icns
|
||||
.com.apple.timemachine.donotpresent
|
||||
|
||||
# Directories potentially created on remote AFP share
|
||||
.AppleDB
|
||||
.AppleDesktop
|
||||
Network Trash Folder
|
||||
Temporary Items
|
||||
.apdisk
|
||||
|
||||
### OSX ###
|
||||
# General
|
||||
|
||||
# Icon must end with two \r
|
||||
|
||||
# Thumbnails
|
||||
|
||||
# Files that might appear in the root of a volume
|
||||
|
||||
# Directories potentially created on remote AFP share
|
||||
|
||||
### PyCharm+all ###
|
||||
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm
|
||||
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
|
||||
|
||||
# User-specific stuff
|
||||
|
||||
# Generated files
|
||||
|
||||
# Sensitive or high-churn files
|
||||
|
||||
# Gradle
|
||||
|
||||
# Gradle and Maven with auto-import
|
||||
# When using Gradle or Maven with auto-import, you should exclude module files,
|
||||
# since they will be recreated, and may cause churn. Uncomment if using
|
||||
# auto-import.
|
||||
# .idea/modules.xml
|
||||
# .idea/*.iml
|
||||
# .idea/modules
|
||||
|
||||
# CMake
|
||||
|
||||
# Mongo Explorer plugin
|
||||
|
||||
# File-based project format
|
||||
|
||||
# IntelliJ
|
||||
|
||||
# mpeltonen/sbt-idea plugin
|
||||
|
||||
# JIRA plugin
|
||||
|
||||
# Cursive Clojure plugin
|
||||
|
||||
# Crashlytics plugin (for Android Studio and IntelliJ)
|
||||
|
||||
# Editor-based Rest Client
|
||||
|
||||
# Android studio 3.1+ serialized cache file
|
||||
|
||||
### PyCharm+all Patch ###
|
||||
# Ignores the whole .idea folder and all .iml files
|
||||
# See https://github.com/joeblau/gitignore.io/issues/186 and https://github.com/joeblau/gitignore.io/issues/360
|
||||
|
||||
|
||||
# Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-249601023
|
||||
|
||||
|
||||
### Vim ###
|
||||
# Swap
|
||||
[._]*.s[a-v][a-z]
|
||||
[._]*.sw[a-p]
|
||||
[._]s[a-rt-v][a-z]
|
||||
[._]ss[a-gi-z]
|
||||
[._]sw[a-p]
|
||||
|
||||
# Session
|
||||
Session.vim
|
||||
|
||||
# Temporary
|
||||
.netrwhist
|
||||
# Auto-generated tag files
|
||||
tags
|
||||
# Persistent undo
|
||||
[._]*.un~
|
||||
|
||||
### VisualStudioCode ###
|
||||
.vscode/*
|
||||
!.vscode/settings.json
|
||||
!.vscode/tasks.json
|
||||
!.vscode/launch.json
|
||||
!.vscode/extensions.json
|
||||
|
||||
### Windows ###
|
||||
# Windows thumbnail cache files
|
||||
Thumbs.db
|
||||
ehthumbs.db
|
||||
ehthumbs_vista.db
|
||||
|
||||
# Dump file
|
||||
*.stackdump
|
||||
|
||||
# Folder config file
|
||||
[Dd]esktop.ini
|
||||
|
||||
# Recycle Bin used on file shares
|
||||
$RECYCLE.BIN/
|
||||
|
||||
# Windows Installer files
|
||||
*.cab
|
||||
*.msi
|
||||
*.msix
|
||||
*.msm
|
||||
*.msp
|
||||
|
||||
# Windows shortcuts
|
||||
*.lnk
|
||||
|
||||
### Xcode ###
|
||||
# Xcode
|
||||
#
|
||||
# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore
|
||||
|
||||
## Build generated
|
||||
build/
|
||||
DerivedData/
|
||||
|
||||
## Various settings
|
||||
*.pbxuser
|
||||
!default.pbxuser
|
||||
*.mode1v3
|
||||
!default.mode1v3
|
||||
*.mode2v3
|
||||
!default.mode2v3
|
||||
*.perspectivev3
|
||||
!default.perspectivev3
|
||||
xcuserdata/
|
||||
|
||||
## Other
|
||||
*.moved-aside
|
||||
*.xccheckout
|
||||
*.xcscmblueprint
|
||||
|
||||
## Obj-C/Swift specific
|
||||
*.hmap
|
||||
*.ipa
|
||||
*.dSYM.zip
|
||||
*.dSYM
|
||||
|
||||
## Playgrounds
|
||||
timeline.xctimeline
|
||||
playground.xcworkspace
|
||||
|
||||
# Swift Package Manager
|
||||
#
|
||||
# Add this line if you want to avoid checking in source code from Swift Package Manager dependencies.
|
||||
# Packages/
|
||||
# Package.pins
|
||||
# Package.resolved
|
||||
.build/
|
||||
|
||||
# CocoaPods
|
||||
#
|
||||
# We recommend against adding the Pods directory to your .gitignore. However
|
||||
# you should judge for yourself, the pros and cons are mentioned at:
|
||||
# https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
|
||||
#
|
||||
# Pods/
|
||||
#
|
||||
# Add this line if you want to avoid checking in source code from the Xcode workspace
|
||||
# *.xcworkspace
|
||||
|
||||
# Carthage
|
||||
#
|
||||
# Add this line if you want to avoid checking in source code from Carthage dependencies.
|
||||
# Carthage/Checkouts
|
||||
|
||||
Carthage/Build
|
||||
|
||||
# fastlane
|
||||
#
|
||||
# It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the
|
||||
# screenshots whenever they are needed.
|
||||
# For more information about the recommended setup visit:
|
||||
# https://docs.fastlane.tools/best-practices/source-control/#source-control
|
||||
|
||||
fastlane/report.xml
|
||||
fastlane/Preview.html
|
||||
fastlane/screenshots/**/*.png
|
||||
fastlane/test_output
|
||||
|
||||
# Code Injection
|
||||
#
|
||||
# After new code Injection tools there's a generated folder /iOSInjectionProject
|
||||
# https://github.com/johnno1962/injectionforxcode
|
||||
|
||||
iOSInjectionProject/
|
||||
|
||||
|
||||
### Xcode Patch ###
|
||||
*.xcodeproj/*
|
||||
!*.xcodeproj/project.pbxproj
|
||||
!*.xcodeproj/xcshareddata/
|
||||
!*.xcworkspace/contents.xcworkspacedata
|
||||
/*.gcno
|
||||
**/xcshareddata/WorkspaceSettings.xcsettings
|
||||
|
||||
### VisualStudio ###
|
||||
## Ignore Visual Studio temporary files, build results, and
|
||||
## files generated by popular Visual Studio add-ons.
|
||||
##
|
||||
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
|
||||
|
||||
# User-specific files
|
||||
*.rsuser
|
||||
*.suo
|
||||
*.user
|
||||
*.userosscache
|
||||
*.sln.docstates
|
||||
|
||||
# User-specific files (MonoDevelop/Xamarin Studio)
|
||||
*.userprefs
|
||||
|
||||
# Build results
|
||||
[Dd]ebug/
|
||||
[Dd]ebugPublic/
|
||||
[Rr]elease/
|
||||
[Rr]eleases/
|
||||
x64/
|
||||
x86/
|
||||
bld/
|
||||
[Bb]in/
|
||||
[Oo]bj/
|
||||
[Ll]og/
|
||||
|
||||
# Visual Studio 2015/2017 cache/options directory
|
||||
.vs/
|
||||
# Uncomment if you have tasks that create the project's static files in wwwroot
|
||||
#wwwroot/
|
||||
|
||||
# Visual Studio 2017 auto generated files
|
||||
Generated\ Files/
|
||||
|
||||
# MSTest test Results
|
||||
[Tt]est[Rr]esult*/
|
||||
[Bb]uild[Ll]og.*
|
||||
|
||||
# NUNIT
|
||||
*.VisualState.xml
|
||||
TestResult.xml
|
||||
|
||||
# Build Results of an ATL Project
|
||||
[Dd]ebugPS/
|
||||
[Rr]eleasePS/
|
||||
dlldata.c
|
||||
|
||||
# Benchmark Results
|
||||
BenchmarkDotNet.Artifacts/
|
||||
|
||||
# .NET Core
|
||||
project.lock.json
|
||||
project.fragment.lock.json
|
||||
artifacts/
|
||||
|
||||
# StyleCop
|
||||
StyleCopReport.xml
|
||||
|
||||
# Files built by Visual Studio
|
||||
*_i.c
|
||||
*_p.c
|
||||
*_h.h
|
||||
*.meta
|
||||
*.iobj
|
||||
*.ipdb
|
||||
*.pgc
|
||||
*.pgd
|
||||
*.rsp
|
||||
*.sbr
|
||||
*.tlb
|
||||
*.tli
|
||||
*.tlh
|
||||
*.tmp
|
||||
*.tmp_proj
|
||||
*_wpftmp.csproj
|
||||
*.log
|
||||
*.vspscc
|
||||
*.vssscc
|
||||
.builds
|
||||
*.pidb
|
||||
*.svclog
|
||||
*.scc
|
||||
|
||||
# Chutzpah Test files
|
||||
_Chutzpah*
|
||||
|
||||
# Visual C++ cache files
|
||||
ipch/
|
||||
*.aps
|
||||
*.ncb
|
||||
*.opendb
|
||||
*.opensdf
|
||||
*.sdf
|
||||
*.cachefile
|
||||
*.VC.db
|
||||
*.VC.VC.opendb
|
||||
|
||||
# Visual Studio profiler
|
||||
*.psess
|
||||
*.vsp
|
||||
*.vspx
|
||||
*.sap
|
||||
|
||||
# Visual Studio Trace Files
|
||||
*.e2e
|
||||
|
||||
# TFS 2012 Local Workspace
|
||||
$tf/
|
||||
|
||||
# Guidance Automation Toolkit
|
||||
*.gpState
|
||||
|
||||
# ReSharper is a .NET coding add-in
|
||||
_ReSharper*/
|
||||
*.[Rr]e[Ss]harper
|
||||
*.DotSettings.user
|
||||
|
||||
# JustCode is a .NET coding add-in
|
||||
.JustCode
|
||||
|
||||
# TeamCity is a build add-in
|
||||
_TeamCity*
|
||||
|
||||
# DotCover is a Code Coverage Tool
|
||||
*.dotCover
|
||||
|
||||
# AxoCover is a Code Coverage Tool
|
||||
.axoCover/*
|
||||
!.axoCover/settings.json
|
||||
|
||||
# Visual Studio code coverage results
|
||||
*.coverage
|
||||
*.coveragexml
|
||||
|
||||
# NCrunch
|
||||
_NCrunch_*
|
||||
.*crunch*.local.xml
|
||||
nCrunchTemp_*
|
||||
|
||||
# MightyMoose
|
||||
*.mm.*
|
||||
AutoTest.Net/
|
||||
|
||||
# Web workbench (sass)
|
||||
.sass-cache/
|
||||
|
||||
# Installshield output folder
|
||||
[Ee]xpress/
|
||||
|
||||
# DocProject is a documentation generator add-in
|
||||
DocProject/buildhelp/
|
||||
DocProject/Help/*.HxT
|
||||
DocProject/Help/*.HxC
|
||||
DocProject/Help/*.hhc
|
||||
DocProject/Help/*.hhk
|
||||
DocProject/Help/*.hhp
|
||||
DocProject/Help/Html2
|
||||
DocProject/Help/html
|
||||
|
||||
# Click-Once directory
|
||||
publish/
|
||||
|
||||
# Publish Web Output
|
||||
*.[Pp]ublish.xml
|
||||
*.azurePubxml
|
||||
# Note: Comment the next line if you want to checkin your web deploy settings,
|
||||
# but database connection strings (with potential passwords) will be unencrypted
|
||||
*.pubxml
|
||||
*.publishproj
|
||||
|
||||
# Microsoft Azure Web App publish settings. Comment the next line if you want to
|
||||
# checkin your Azure Web App publish settings, but sensitive information contained
|
||||
# in these scripts will be unencrypted
|
||||
PublishScripts/
|
||||
|
||||
# NuGet Packages
|
||||
*.nupkg
|
||||
# The packages folder can be ignored because of Package Restore
|
||||
**/[Pp]ackages/*
|
||||
# except build/, which is used as an MSBuild target.
|
||||
!**/[Pp]ackages/build/
|
||||
# Uncomment if necessary however generally it will be regenerated when needed
|
||||
#!**/[Pp]ackages/repositories.config
|
||||
# NuGet v3's project.json files produces more ignorable files
|
||||
*.nuget.props
|
||||
*.nuget.targets
|
||||
|
||||
# Microsoft Azure Build Output
|
||||
csx/
|
||||
*.build.csdef
|
||||
|
||||
# Microsoft Azure Emulator
|
||||
ecf/
|
||||
rcf/
|
||||
|
||||
# Windows Store app package directories and files
|
||||
AppPackages/
|
||||
BundleArtifacts/
|
||||
Package.StoreAssociation.xml
|
||||
_pkginfo.txt
|
||||
*.appx
|
||||
|
||||
# Visual Studio cache files
|
||||
# files ending in .cache can be ignored
|
||||
*.[Cc]ache
|
||||
# but keep track of directories ending in .cache
|
||||
!*.[Cc]ache/
|
||||
|
||||
# Others
|
||||
ClientBin/
|
||||
~$*
|
||||
*.dbmdl
|
||||
*.dbproj.schemaview
|
||||
*.jfm
|
||||
*.pfx
|
||||
*.publishsettings
|
||||
orleans.codegen.cs
|
||||
|
||||
# Including strong name files can present a security risk
|
||||
# (https://github.com/github/gitignore/pull/2483#issue-259490424)
|
||||
#*.snk
|
||||
|
||||
# Since there are multiple workflows, uncomment next line to ignore bower_components
|
||||
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
|
||||
#bower_components/
|
||||
|
||||
# RIA/Silverlight projects
|
||||
Generated_Code/
|
||||
|
||||
# Backup & report files from converting an old project file
|
||||
# to a newer Visual Studio version. Backup files are not needed,
|
||||
# because we have git ;-)
|
||||
_UpgradeReport_Files/
|
||||
Backup*/
|
||||
UpgradeLog*.XML
|
||||
UpgradeLog*.htm
|
||||
ServiceFabricBackup/
|
||||
*.rptproj.bak
|
||||
|
||||
# SQL Server files
|
||||
*.mdf
|
||||
*.ldf
|
||||
*.ndf
|
||||
|
||||
# Business Intelligence projects
|
||||
*.rdl.data
|
||||
*.bim.layout
|
||||
*.bim_*.settings
|
||||
*.rptproj.rsuser
|
||||
|
||||
# Microsoft Fakes
|
||||
FakesAssemblies/
|
||||
|
||||
# GhostDoc plugin setting file
|
||||
*.GhostDoc.xml
|
||||
|
||||
# Node.js Tools for Visual Studio
|
||||
.ntvs_analysis.dat
|
||||
node_modules/
|
||||
|
||||
# Visual Studio 6 build log
|
||||
*.plg
|
||||
|
||||
# Visual Studio 6 workspace options file
|
||||
*.opt
|
||||
|
||||
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
|
||||
*.vbw
|
||||
|
||||
# Visual Studio LightSwitch build output
|
||||
**/*.HTMLClient/GeneratedArtifacts
|
||||
**/*.DesktopClient/GeneratedArtifacts
|
||||
**/*.DesktopClient/ModelManifest.xml
|
||||
**/*.Server/GeneratedArtifacts
|
||||
**/*.Server/ModelManifest.xml
|
||||
_Pvt_Extensions
|
||||
|
||||
# Paket dependency manager
|
||||
.paket/paket.exe
|
||||
paket-files/
|
||||
|
||||
# FAKE - F# Make
|
||||
.fake/
|
||||
|
||||
# JetBrains Rider
|
||||
*.sln.iml
|
||||
|
||||
# CodeRush personal settings
|
||||
.cr/personal
|
||||
|
||||
# Python Tools for Visual Studio (PTVS)
|
||||
__pycache__/
|
||||
*.pyc
|
||||
|
||||
# Cake - Uncomment if you are using it
|
||||
# tools/**
|
||||
# !tools/packages.config
|
||||
|
||||
# Tabs Studio
|
||||
*.tss
|
||||
|
||||
# Telerik's JustMock configuration file
|
||||
*.jmconfig
|
||||
|
||||
# BizTalk build output
|
||||
*.btp.cs
|
||||
*.btm.cs
|
||||
*.odx.cs
|
||||
*.xsd.cs
|
||||
|
||||
# OpenCover UI analysis results
|
||||
OpenCover/
|
||||
|
||||
# Azure Stream Analytics local run output
|
||||
ASALocalRun/
|
||||
|
||||
# MSBuild Binary and Structured Log
|
||||
*.binlog
|
||||
|
||||
# NVidia Nsight GPU debugger configuration file
|
||||
*.nvuser
|
||||
|
||||
# MFractors (Xamarin productivity tool) working folder
|
||||
.mfractor/
|
||||
|
||||
# Local History for Visual Studio
|
||||
.localhistory/
|
||||
|
||||
# End of https://www.gitignore.io/api/visualstudiocode,windows,c,c++,cmake,codeblocks,intellij+all,jetbrains+all,kdevelop4,linux,macos,osx,pycharm+all,vim,visualstudio,xcode
|
||||
|
||||
# Custom rules (everything added below won't be overriden by 'Generate .gitignore File' if you use 'Update' option)
|
||||
|
||||
kendryte-standlone-sdk.si4project/
|
||||
|
||||
kendryte-standalone-demo
|
||||
kendryte-standalone-demo-bak
|
||||
src/
|
||||
!src/hello_world
|
||||
/CMakeSettings.json
|
||||
/build_i
|
||||
@@ -1,74 +0,0 @@
|
||||
sudo: false
|
||||
language: cpp
|
||||
git:
|
||||
submodules: false
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- python
|
||||
- python-pip
|
||||
- git
|
||||
- wget
|
||||
- make
|
||||
- cmake
|
||||
- libncurses-dev
|
||||
- flex
|
||||
- bison
|
||||
- gperf
|
||||
- aria2
|
||||
cache:
|
||||
- pip
|
||||
- directories:
|
||||
- cache
|
||||
before_install:
|
||||
- export TOOLCHAIN_URL=https://github.com/kendryte/kendryte-gnu-toolchain/releases/download/v8.2.0-20190213/kendryte-toolchain-ubuntu-amd64-8.2.0-20190213.tar.gz
|
||||
- export TOOLCHAIN=${TOOLCHAIN_URL##*/}
|
||||
- |
|
||||
if [ ! -f $TRAVIS_BUILD_DIR/cache/$TOOLCHAIN ]; then
|
||||
echo "Download toolchain ..."
|
||||
aria2c $TOOLCHAIN_URL -d $TRAVIS_BUILD_DIR/cache -o $TOOLCHAIN
|
||||
else
|
||||
echo "Toolchain is ready download in cache"
|
||||
fi
|
||||
- |
|
||||
if [ ! -d $TRAVIS_BUILD_DIR/cache/kendryte-toolchain ]; then
|
||||
echo "Extract toolchain ..."
|
||||
tar -C $TRAVIS_BUILD_DIR/cache -zxvf $TRAVIS_BUILD_DIR/cache/$TOOLCHAIN
|
||||
else
|
||||
echo "Toolchain is ready extract in cache"
|
||||
fi
|
||||
install:
|
||||
- export PATH=$TRAVIS_BUILD_DIR/cache/kendryte-toolchain/bin:$PATH
|
||||
- export LD_LIBRARY_PATH=$TRAVIS_BUILD_DIR/cache/kendryte-toolchain/bin:$LD_LIBRARY_PATH
|
||||
- |
|
||||
cd $TRAVIS_BUILD_DIR
|
||||
export BRANCH=$(if [ "$TRAVIS_BRANCH" == "master" ]; then echo $TRAVIS_BRANCH; else echo "develop"; fi)
|
||||
git clone --single-branch --branch $BRANCH https://github.com/kendryte/kendryte-standalone-demo.git
|
||||
echo "Build branch $BRANCH"
|
||||
|
||||
script:
|
||||
- export BUILD_DATE=$(date +%Y%m%d)
|
||||
## Copy all example code
|
||||
- |
|
||||
cd $TRAVIS_BUILD_DIR/src
|
||||
cp -rf $TRAVIS_BUILD_DIR/kendryte-standalone-demo/* .
|
||||
mv $TRAVIS_BUILD_DIR/kendryte-standalone-demo ~/demo
|
||||
## Check example code
|
||||
- |
|
||||
for DIR in $(ls $TRAVIS_BUILD_DIR/src)
|
||||
do
|
||||
echo "[MAKE]" $TRAVIS_BUILD_DIR/src/$DIR
|
||||
cd $TRAVIS_BUILD_DIR/src/$DIR
|
||||
if [ ! -f "Makefile" ]; then
|
||||
COUNT=$(expr $(ls -1 *.c 2>/dev/null | wc -l) + $(ls -1 *.cpp 2>/dev/null | wc -l) + $(ls -1 *.S 2>/dev/null | wc -l))
|
||||
if [ $COUNT -gt 0 ]; then
|
||||
mkdir build && cd build
|
||||
cmake -DPROJ=$DIR -DTOOLCHAIN=$TRAVIS_BUILD_DIR/cache/kendryte-toolchain/bin ../../../ || exit -1
|
||||
make || exit -1
|
||||
else
|
||||
echo "[IGNORE]" $TRAVIS_BUILD_DIR/src/$DIR
|
||||
fi
|
||||
else
|
||||
make || exit -1
|
||||
fi
|
||||
done
|
||||
@@ -1,94 +0,0 @@
|
||||
Changelog for Kendryte K210
|
||||
======
|
||||
|
||||
## 0.1.0
|
||||
|
||||
Kendryte K210 first SDK with FreeRTOS, have fun.
|
||||
|
||||
## 0.2.0
|
||||
|
||||
- Major changes
|
||||
- Rework trap handling
|
||||
- New functions to enable spi0 and dvp pin
|
||||
- New functions to select IO power mode
|
||||
- Breaking changes
|
||||
- Modify struct enum union format
|
||||
- Non-breaking bug fixes
|
||||
- Fix spi lcd unwork issues
|
||||
- Fix dual core startup issues
|
||||
- Use "__global_pointer$" instead of "_gp"
|
||||
|
||||
## 0.3.0
|
||||
|
||||
- Major change
|
||||
- Modify AES、FFT、SHA、I2C、SPI、WDT、SPI driver
|
||||
- Breaking changes
|
||||
- Modify struct enum union format
|
||||
- Non-breaking bug fixes
|
||||
- Fix out of memory issues
|
||||
- Fix lcd unused issues
|
||||
|
||||
## 0.4.1
|
||||
|
||||
- Major change
|
||||
- Add dma support for aes driver
|
||||
- Add uarths driver
|
||||
- Add dma interrupt handler
|
||||
|
||||
- Non-breaking bug fixes
|
||||
- Fix the procedure of setting pll
|
||||
- Fix wdt interrupt bug
|
||||
- Fix serveral bugs in i2s drivers
|
||||
|
||||
## 0.5.0
|
||||
|
||||
- Major change
|
||||
- Add KPU driver
|
||||
- Find toolchain automatically
|
||||
|
||||
- Non-breaking bug fixes
|
||||
- Fix aes gcm bug
|
||||
- Fix dmac interrupt bug
|
||||
- Fix i2s transfer bug
|
||||
|
||||
## 0.5.1
|
||||
|
||||
- Major changes
|
||||
- Add i2c slave driver
|
||||
|
||||
- Non-breaking bug fixes
|
||||
- Fix pll init issues
|
||||
- Fix spi receive mode issues
|
||||
- Fix redefine function does not report error issues
|
||||
- Reduce stack size
|
||||
|
||||
## 0.5.2
|
||||
- Major change
|
||||
- Add KPU driver for latest model compiler
|
||||
- Automatic set PROJ if user not set it
|
||||
- Update timer driver to support better interrupt
|
||||
- Add uart dma and interrupt function
|
||||
- Non-breaking bug fixes
|
||||
- Fix rtc issues
|
||||
- Fix sccb issues
|
||||
|
||||
- Breaking change
|
||||
- Fix timer interrupt lost problem
|
||||
- Add new timer interrupt API
|
||||
|
||||
## 0.5.3
|
||||
- Major change
|
||||
- Modify KPU driver for latest model compiler
|
||||
- Add freertos
|
||||
- Add new gpiohs and wdt interrupt function
|
||||
- Add dvp xclk setting
|
||||
- Add sysctl reset status
|
||||
|
||||
- Non-breaking bug fixes
|
||||
- Fix i2c issues
|
||||
- Fix spi issues
|
||||
|
||||
- Breaking change
|
||||
- Fix uarths stopbit problem
|
||||
- Fix core1 stack problem
|
||||
- Fix core1 interrupt problem
|
||||
@@ -1,31 +0,0 @@
|
||||
### This file is used for build example projects.
|
||||
|
||||
# set this will supress some warnings
|
||||
set(BUILDING_SDK "yes" CACHE INTERNAL "")
|
||||
|
||||
# basic config
|
||||
if (NOT PROJ)
|
||||
get_filename_component(PROJ ${CMAKE_CURRENT_BINARY_DIR} DIRECTORY)
|
||||
get_filename_component(PROJ ${PROJ} NAME)
|
||||
string(REPLACE " " "_" PROJ ${PROJ})
|
||||
message(STATUS "PROJ not set, use ${PROJ} as PROJ. Also, you can set it manually. e.g. -DPROJ=hello_world")
|
||||
else()
|
||||
message("PROJ = ${PROJ}")
|
||||
endif ()
|
||||
cmake_minimum_required(VERSION 3.0)
|
||||
include(./cmake/common.cmake)
|
||||
project(${PROJ} C CXX ASM)
|
||||
|
||||
# config self use headers
|
||||
include(./cmake/macros.internal.cmake)
|
||||
header_directories(${SDK_ROOT}/lib)
|
||||
header_directories(src/${PROJ})
|
||||
header_directories(kendryte-standalone-demo/${PROJ})
|
||||
# build library first
|
||||
add_subdirectory(lib)
|
||||
|
||||
# compile project
|
||||
add_source_files(src/${PROJ}/*.c src/${PROJ}/*.s src/${PROJ}/*.S src/${PROJ}/*.cpp)
|
||||
add_source_files(kendryte-standalone-demo/${PROJ}/*.c kendryte-standalone-demo/${PROJ}/*.s kendryte-standalone-demo/${PROJ}/*.S kendryte-standalone-demo/${PROJ}/*.cpp)
|
||||
include(./cmake/executable.cmake)
|
||||
|
||||
@@ -1,202 +0,0 @@
|
||||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright 2018 Canaan Inc.
|
||||
|
||||
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
|
||||
|
||||
http://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.
|
||||
@@ -1,25 +0,0 @@
|
||||
# Kendryte K210 standalone SDK
|
||||
|
||||
[](https://travis-ci.org/kendryte/kendryte-standalone-sdk)
|
||||
[](https://opensource.org/licenses/Apache-2.0)
|
||||
|
||||
This SDK is for Kendryte K210 without OS support.
|
||||
If you have any questions, please be free to contact us.
|
||||
|
||||
## Usage
|
||||
|
||||
If you want to start a new project, for instance, `hello_world`, you only need to:
|
||||
|
||||
`mkdir` your project in `src/`, `cd src && mkdir hello_world`, then put your codes in it, and build it.
|
||||
|
||||
```bash
|
||||
mkdir build && cd build
|
||||
cmake .. -DPROJ=<ProjectName> -DTOOLCHAIN=/opt/riscv-toolchain/bin && make
|
||||
```
|
||||
|
||||
You will get 2 key files, `hello_world` and `hello_world.bin`.
|
||||
|
||||
1. If you are using JLink to run or debug your program, use `hello_world`
|
||||
2. If you want to flash it in UOG, using `hello_world.bin`, then using flash-tool(s) burn <ProjectName>.bin to your flash.
|
||||
|
||||
This is very important, don't make a mistake in files.
|
||||
@@ -1,252 +0,0 @@
|
||||
/*
|
||||
* The MEMORY command describes the location and size of blocks of memory
|
||||
* in the target. You can use it to describe which memory regions may be
|
||||
* used by the linker, and which memory regions it must avoid.
|
||||
*/
|
||||
MEMORY
|
||||
{
|
||||
/*
|
||||
* Memory with CPU cache.
|
||||
*6M CPU SRAM
|
||||
*/
|
||||
ram (wxa!ri) : ORIGIN = 0x80000000, LENGTH = (6 * 1024 * 1024)
|
||||
/*
|
||||
* Memory without CPU cache
|
||||
* 6M CPU SRAM
|
||||
*/
|
||||
ram_nocache (wxa!ri) : ORIGIN = 0x40000000, LENGTH = (6 * 1024 * 1024)
|
||||
}
|
||||
|
||||
PROVIDE( _rom_start = ORIGIN(rom) );
|
||||
PROVIDE( _rom_end = ORIGIN(rom) + LENGTH(rom) );
|
||||
PROVIDE( _ram_start = ORIGIN(ram) );
|
||||
PROVIDE( _ram_end = ORIGIN(ram) + LENGTH(ram) );
|
||||
PROVIDE( _io_start = 0x40000000 );
|
||||
PROVIDE( _io_end = _io_start + LENGTH(ram) );
|
||||
PROVIDE( _stack_size = 1 << 15 );
|
||||
|
||||
|
||||
/*
|
||||
* The OUTPUT_ARCH command specifies the machine architecture where the
|
||||
* argument is one of the names used in the Kendryte library.
|
||||
*/
|
||||
OUTPUT_ARCH( "riscv" )
|
||||
|
||||
/*
|
||||
* The ENTRY command specifies the entry point (ie. first instruction to
|
||||
* execute). The symbol _start is defined in crt0.S
|
||||
*/
|
||||
ENTRY(_start)
|
||||
|
||||
/*
|
||||
* The GROUP command is special since the listed archives will be
|
||||
* searched repeatedly until there are no new undefined references. We
|
||||
* need this since -lc depends on -lgloss and -lgloss depends on -lc. I
|
||||
* thought gcc would automatically include -lgcc when needed, but
|
||||
* in this file includes it explicitly here and I was seeing link errors
|
||||
* without it.
|
||||
*/
|
||||
/* GROUP( -lc -lgloss -lgcc ) */
|
||||
|
||||
/*
|
||||
* The linker only pays attention to the PHDRS command when generating
|
||||
* an ELF output file. In other cases, the linker will simply ignore PHDRS.
|
||||
*/
|
||||
PHDRS
|
||||
{
|
||||
ram_ro PT_LOAD;
|
||||
ram_init PT_LOAD;
|
||||
ram PT_NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* This is where we specify how the input sections map to output
|
||||
* sections.
|
||||
*/
|
||||
SECTIONS
|
||||
{
|
||||
/* Program code segment, also known as a text segment */
|
||||
.text :
|
||||
{
|
||||
PROVIDE( _text = ABSOLUTE(.) );
|
||||
/* Initialization code segment */
|
||||
KEEP( *(.text.start) )
|
||||
KEEP( *(.text.systick) )
|
||||
*(.text.unlikely .text.unlikely.*)
|
||||
*(.text.startup .text.startup.*)
|
||||
/* Normal code segment */
|
||||
*(.text .text.*)
|
||||
*(.gnu.linkonce.t.*)
|
||||
|
||||
. = ALIGN(8);
|
||||
PROVIDE( _etext = ABSOLUTE(.) );
|
||||
} >ram AT>ram :ram_ro
|
||||
|
||||
/* Read-only data segment */
|
||||
.rodata :
|
||||
{
|
||||
*(.rdata)
|
||||
*(.rodata .rodata.*)
|
||||
*(.gnu.linkonce.r.*)
|
||||
} >ram AT>ram :ram_ro
|
||||
|
||||
. = ALIGN(8);
|
||||
|
||||
/* Init array and fini array */
|
||||
.preinit_array :
|
||||
{
|
||||
PROVIDE_HIDDEN (__preinit_array_start = .);
|
||||
KEEP (*(.preinit_array))
|
||||
PROVIDE_HIDDEN (__preinit_array_end = .);
|
||||
} >ram AT>ram :ram_ro
|
||||
|
||||
.init_array :
|
||||
{
|
||||
PROVIDE_HIDDEN (__init_array_start = .);
|
||||
KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*)))
|
||||
KEEP (*(.init_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .ctors))
|
||||
PROVIDE_HIDDEN (__init_array_end = .);
|
||||
} >ram AT>ram :ram_ro
|
||||
|
||||
.fini_array :
|
||||
{
|
||||
PROVIDE_HIDDEN (__fini_array_start = .);
|
||||
KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*)))
|
||||
KEEP (*(.fini_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .dtors))
|
||||
PROVIDE_HIDDEN (__fini_array_end = .);
|
||||
} >ram AT>ram :ram_ro
|
||||
|
||||
.ctors :
|
||||
{
|
||||
/* gcc uses crtbegin.o to find the start of
|
||||
the constructors, so we make sure it is
|
||||
first. Because this is a wildcard, it
|
||||
doesn't matter if the user does not
|
||||
actually link against crtbegin.o; the
|
||||
linker won't look for a file to match a
|
||||
wildcard. The wildcard also means that it
|
||||
doesn't matter which directory crtbegin.o
|
||||
is in. */
|
||||
KEEP (*crtbegin.o(.ctors))
|
||||
KEEP (*crtbegin?.o(.ctors))
|
||||
/* We don't want to include the .ctor section from
|
||||
the crtend.o file until after the sorted ctors.
|
||||
The .ctor section from the crtend file contains the
|
||||
end of ctors marker and it must be last */
|
||||
KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors))
|
||||
KEEP (*(SORT(.ctors.*)))
|
||||
KEEP (*(.ctors))
|
||||
} >ram AT>ram :ram_ro
|
||||
|
||||
.dtors :
|
||||
{
|
||||
KEEP (*crtbegin.o(.dtors))
|
||||
KEEP (*crtbegin?.o(.dtors))
|
||||
KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors))
|
||||
KEEP (*(SORT(.dtors.*)))
|
||||
KEEP (*(.dtors))
|
||||
} >ram AT>ram :ram_ro
|
||||
|
||||
. = ALIGN(8);
|
||||
|
||||
.lalign :
|
||||
{
|
||||
. = ALIGN(8);
|
||||
PROVIDE( _data_lma = . );
|
||||
} >ram AT>ram :ram_ro
|
||||
|
||||
.dalign :
|
||||
{
|
||||
. = ALIGN(8);
|
||||
PROVIDE( _data = . );
|
||||
} >ram AT>ram :ram_init
|
||||
|
||||
. = ALIGN(8);
|
||||
|
||||
/* .data, .sdata and .srodata segment */
|
||||
.data :
|
||||
{
|
||||
/* Writable data segment (.data segment) */
|
||||
*(.data .data.*)
|
||||
*(.gnu.linkonce.d.*)
|
||||
/* Have _gp point to middle of sdata/sbss to maximize displacement range */
|
||||
. = ALIGN(8);
|
||||
PROVIDE( __global_pointer$ = ABSOLUTE(.) + 0x800);
|
||||
/* Writable small data segment (.sdata segment) */
|
||||
*(.sdata .sdata.*)
|
||||
*(.gnu.linkonce.s.*)
|
||||
/* Read-only small data segment (.srodata segment) */
|
||||
. = ALIGN(8);
|
||||
*(.srodata.cst16)
|
||||
*(.srodata.cst8)
|
||||
*(.srodata.cst4)
|
||||
*(.srodata.cst2)
|
||||
*(.srodata .srodata.*)
|
||||
/* Align _edata to cache line size */
|
||||
. = ALIGN(64);
|
||||
PROVIDE( _edata = ABSOLUTE(.) );
|
||||
} >ram AT>ram :ram_init
|
||||
|
||||
/* .bss and .sbss segment */
|
||||
.bss :
|
||||
{
|
||||
PROVIDE( _bss = ABSOLUTE(.) );
|
||||
/* Writable uninitialized small data segment (.sbss segment)*/
|
||||
*(.sbss .sbss.*)
|
||||
*(.gnu.linkonce.sb.*)
|
||||
*(.scommon)
|
||||
/* Uninitialized writeable data section (.bss segment)*/
|
||||
*(.bss .bss.*)
|
||||
*(.gnu.linkonce.b.*)
|
||||
*(COMMON)
|
||||
|
||||
. = ALIGN(8);
|
||||
PROVIDE( _ebss = ABSOLUTE(.) );
|
||||
} >ram AT>ram :ram
|
||||
|
||||
PROVIDE( _tls_data = ABSOLUTE(.) );
|
||||
/*
|
||||
* Thread Local Storage (TLS) are per-thread global variables.
|
||||
* Compilers such as GCC provide a __thread keyword to mark global
|
||||
* variables as per-thread. Support is required in the program loader
|
||||
* and thread creator.
|
||||
*/
|
||||
|
||||
/* Thread-local data segment, .tdata (initialized tls). */
|
||||
.tdata :
|
||||
{
|
||||
KEEP( *(.tdata.begin) )
|
||||
*(.tdata .tdata.*)
|
||||
*(.gnu.linkonce.td.*)
|
||||
KEEP( *(.tdata.end) )
|
||||
} >ram AT>ram :ram
|
||||
|
||||
/* Thread-local bss segment, .tbss (zero-initialized tls). */
|
||||
.tbss :
|
||||
{
|
||||
*(.tbss .tbss.*)
|
||||
*(.gnu.linkonce.tb.*)
|
||||
KEEP( *(.tbss.end) )
|
||||
} >ram AT>ram :ram
|
||||
|
||||
/*
|
||||
* End of uninitalized data segement
|
||||
*
|
||||
* Actually the stack needs 16B alignment, and it won't hurt to also slightly
|
||||
* increase the alignment to 32 or even 64 (cache line size).
|
||||
*
|
||||
* Align _heap_start to cache line size
|
||||
*/
|
||||
. = ALIGN(64);
|
||||
PROVIDE( _end = ABSOLUTE(.) );
|
||||
/* Leave 2 holes for stack & TLS, the size can set in kconfig */
|
||||
PROVIDE( _heap_start = ABSOLUTE(.) + _stack_size * 2 );
|
||||
PROVIDE( _tp0 = (_end + 63) & (-64) );
|
||||
PROVIDE( _tp1 = _tp0 + _stack_size );
|
||||
PROVIDE( _sp0 = _tp0 + _stack_size );
|
||||
PROVIDE( _sp1 = _tp1 + _stack_size );
|
||||
|
||||
/* Heap end is at the end of memory, the memory size can set in kconfig */
|
||||
PROVIDE( _heap_end = _ram_end );
|
||||
}
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
#project(maix_drivers)
|
||||
|
||||
# create driver library
|
||||
|
||||
FILE(GLOB_RECURSE LIB_SRC
|
||||
"${CMAKE_CURRENT_LIST_DIR}/*.h"
|
||||
"${CMAKE_CURRENT_LIST_DIR}/*.hpp"
|
||||
"${CMAKE_CURRENT_LIST_DIR}/*.cpp"
|
||||
"${CMAKE_CURRENT_LIST_DIR}/*.c"
|
||||
"${CMAKE_CURRENT_LIST_DIR}/*.s"
|
||||
"${CMAKE_CURRENT_LIST_DIR}/*.S"
|
||||
)
|
||||
|
||||
FILE(GLOB_RECURSE ASSEMBLY_FILES
|
||||
"${CMAKE_CURRENT_LIST_DIR}/*.s"
|
||||
"${CMAKE_CURRENT_LIST_DIR}/*.S"
|
||||
)
|
||||
|
||||
include_directories(${CMAKE_CURRENT_LIST_DIR}/drivers/include ${CMAKE_CURRENT_LIST_DIR}/bsp/include)
|
||||
|
||||
SET_PROPERTY(SOURCE ${ASSEMBLY_FILES} PROPERTY LANGUAGE C)
|
||||
SET_SOURCE_FILES_PROPERTIES(${ASSEMBLY_FILES} PROPERTIES COMPILE_FLAGS "-x assembler-with-cpp -D __riscv64")
|
||||
|
||||
ADD_LIBRARY(kendryte
|
||||
${LIB_SRC}
|
||||
)
|
||||
SET_TARGET_PROPERTIES(kendryte PROPERTIES LINKER_LANGUAGE C)
|
||||
@@ -1,318 +0,0 @@
|
||||
# Copyright 2018 Canaan Inc.
|
||||
#
|
||||
# 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
|
||||
#
|
||||
# http://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.
|
||||
|
||||
#include "encoding.h"
|
||||
|
||||
# define LREG ld
|
||||
# define SREG sd
|
||||
# define LFREG flw
|
||||
# define SFREG fsw
|
||||
# define REGBYTES 8
|
||||
# define STKSHIFT 15
|
||||
|
||||
|
||||
.section .text.start, "ax", @progbits
|
||||
.globl _start
|
||||
_start:
|
||||
j 1f
|
||||
.word 0xdeadbeef
|
||||
.align 3
|
||||
.global g_wake_up
|
||||
g_wake_up:
|
||||
.dword 1
|
||||
.dword 0
|
||||
1:
|
||||
csrw mideleg, 0
|
||||
csrw medeleg, 0
|
||||
csrw mie, 0
|
||||
csrw mip, 0
|
||||
la t0, trap_entry
|
||||
csrw mtvec, t0
|
||||
|
||||
li x1, 0
|
||||
li x2, 0
|
||||
li x3, 0
|
||||
li x4, 0
|
||||
li x5, 0
|
||||
li x6, 0
|
||||
li x7, 0
|
||||
li x8, 0
|
||||
li x9, 0
|
||||
li x10,0
|
||||
li x11,0
|
||||
li x12,0
|
||||
li x13,0
|
||||
li x14,0
|
||||
li x15,0
|
||||
li x16,0
|
||||
li x17,0
|
||||
li x18,0
|
||||
li x19,0
|
||||
li x20,0
|
||||
li x21,0
|
||||
li x22,0
|
||||
li x23,0
|
||||
li x24,0
|
||||
li x25,0
|
||||
li x26,0
|
||||
li x27,0
|
||||
li x28,0
|
||||
li x29,0
|
||||
li x30,0
|
||||
li x31,0
|
||||
|
||||
li t0, MSTATUS_FS
|
||||
csrs mstatus, t0
|
||||
|
||||
fssr x0
|
||||
fmv.w.x f0, x0
|
||||
fmv.w.x f1, x0
|
||||
fmv.w.x f2, x0
|
||||
fmv.w.x f3, x0
|
||||
fmv.w.x f4, x0
|
||||
fmv.w.x f5, x0
|
||||
fmv.w.x f6, x0
|
||||
fmv.w.x f7, x0
|
||||
fmv.w.x f8, x0
|
||||
fmv.w.x f9, x0
|
||||
fmv.w.x f10,x0
|
||||
fmv.w.x f11,x0
|
||||
fmv.w.x f12,x0
|
||||
fmv.w.x f13,x0
|
||||
fmv.w.x f14,x0
|
||||
fmv.w.x f15,x0
|
||||
fmv.w.x f16,x0
|
||||
fmv.w.x f17,x0
|
||||
fmv.w.x f18,x0
|
||||
fmv.w.x f19,x0
|
||||
fmv.w.x f20,x0
|
||||
fmv.w.x f21,x0
|
||||
fmv.w.x f22,x0
|
||||
fmv.w.x f23,x0
|
||||
fmv.w.x f24,x0
|
||||
fmv.w.x f25,x0
|
||||
fmv.w.x f26,x0
|
||||
fmv.w.x f27,x0
|
||||
fmv.w.x f28,x0
|
||||
fmv.w.x f29,x0
|
||||
fmv.w.x f30,x0
|
||||
fmv.w.x f31,x0
|
||||
|
||||
.option push
|
||||
.option norelax
|
||||
la gp, __global_pointer$
|
||||
.option pop
|
||||
la tp, _end + 63
|
||||
and tp, tp, -64
|
||||
csrr a0, mhartid
|
||||
|
||||
add sp, a0, 1
|
||||
sll sp, sp, STKSHIFT
|
||||
add sp, sp, tp
|
||||
|
||||
j _init_bsp
|
||||
|
||||
.globl trap_entry
|
||||
.type trap_entry, @function
|
||||
.align 2
|
||||
trap_entry:
|
||||
addi sp, sp, -REGBYTES
|
||||
sd t0, 0x0(sp)
|
||||
csrr t0, mcause
|
||||
bgez t0, .handle_other
|
||||
# Test soft interrupt
|
||||
slli t0, t0, 1
|
||||
addi t0, t0, -(IRQ_M_SOFT << 1)
|
||||
bnez t0, .handle_other
|
||||
# Interupt is soft interrupt
|
||||
# Get event
|
||||
addi sp, sp, -REGBYTES
|
||||
sd t1, 0x0(sp)
|
||||
la t0, g_core_pending_switch
|
||||
csrr t1, mhartid
|
||||
slli t1, t1, 3
|
||||
add t0, t0, t1
|
||||
ld t1, 0x0(sp)
|
||||
addi sp, sp, REGBYTES
|
||||
# Test ContextSwitch event
|
||||
ld t0, 0x0(t0)
|
||||
beqz t0, .handle_other
|
||||
|
||||
ld t0, 0x0(sp)
|
||||
addi sp, sp, REGBYTES
|
||||
# Do not use jal here
|
||||
j xPortSysTickInt
|
||||
mret
|
||||
.handle_other:
|
||||
ld t0, 0x0(sp)
|
||||
addi sp, sp, REGBYTES
|
||||
addi sp, sp, -64*REGBYTES
|
||||
|
||||
SREG x1, 1*REGBYTES(sp)
|
||||
SREG x2, 2*REGBYTES(sp)
|
||||
SREG x3, 3*REGBYTES(sp)
|
||||
SREG x4, 4*REGBYTES(sp)
|
||||
SREG x5, 5*REGBYTES(sp)
|
||||
SREG x6, 6*REGBYTES(sp)
|
||||
SREG x7, 7*REGBYTES(sp)
|
||||
SREG x8, 8*REGBYTES(sp)
|
||||
SREG x9, 9*REGBYTES(sp)
|
||||
SREG x10, 10*REGBYTES(sp)
|
||||
SREG x11, 11*REGBYTES(sp)
|
||||
SREG x12, 12*REGBYTES(sp)
|
||||
SREG x13, 13*REGBYTES(sp)
|
||||
SREG x14, 14*REGBYTES(sp)
|
||||
SREG x15, 15*REGBYTES(sp)
|
||||
SREG x16, 16*REGBYTES(sp)
|
||||
SREG x17, 17*REGBYTES(sp)
|
||||
SREG x18, 18*REGBYTES(sp)
|
||||
SREG x19, 19*REGBYTES(sp)
|
||||
SREG x20, 20*REGBYTES(sp)
|
||||
SREG x21, 21*REGBYTES(sp)
|
||||
SREG x22, 22*REGBYTES(sp)
|
||||
SREG x23, 23*REGBYTES(sp)
|
||||
SREG x24, 24*REGBYTES(sp)
|
||||
SREG x25, 25*REGBYTES(sp)
|
||||
SREG x26, 26*REGBYTES(sp)
|
||||
SREG x27, 27*REGBYTES(sp)
|
||||
SREG x28, 28*REGBYTES(sp)
|
||||
SREG x29, 29*REGBYTES(sp)
|
||||
SREG x30, 30*REGBYTES(sp)
|
||||
SREG x31, 31*REGBYTES(sp)
|
||||
|
||||
SFREG f0, ( 0 + 32)*REGBYTES(sp)
|
||||
SFREG f1, ( 1 + 32)*REGBYTES(sp)
|
||||
SFREG f2, ( 2 + 32)*REGBYTES(sp)
|
||||
SFREG f3, ( 3 + 32)*REGBYTES(sp)
|
||||
SFREG f4, ( 4 + 32)*REGBYTES(sp)
|
||||
SFREG f5, ( 5 + 32)*REGBYTES(sp)
|
||||
SFREG f6, ( 6 + 32)*REGBYTES(sp)
|
||||
SFREG f7, ( 7 + 32)*REGBYTES(sp)
|
||||
SFREG f8, ( 8 + 32)*REGBYTES(sp)
|
||||
SFREG f9, ( 9 + 32)*REGBYTES(sp)
|
||||
SFREG f10,( 10 + 32)*REGBYTES(sp)
|
||||
SFREG f11,( 11 + 32)*REGBYTES(sp)
|
||||
SFREG f12,( 12 + 32)*REGBYTES(sp)
|
||||
SFREG f13,( 13 + 32)*REGBYTES(sp)
|
||||
SFREG f14,( 14 + 32)*REGBYTES(sp)
|
||||
SFREG f15,( 15 + 32)*REGBYTES(sp)
|
||||
SFREG f16,( 16 + 32)*REGBYTES(sp)
|
||||
SFREG f17,( 17 + 32)*REGBYTES(sp)
|
||||
SFREG f18,( 18 + 32)*REGBYTES(sp)
|
||||
SFREG f19,( 19 + 32)*REGBYTES(sp)
|
||||
SFREG f20,( 20 + 32)*REGBYTES(sp)
|
||||
SFREG f21,( 21 + 32)*REGBYTES(sp)
|
||||
SFREG f22,( 22 + 32)*REGBYTES(sp)
|
||||
SFREG f23,( 23 + 32)*REGBYTES(sp)
|
||||
SFREG f24,( 24 + 32)*REGBYTES(sp)
|
||||
SFREG f25,( 25 + 32)*REGBYTES(sp)
|
||||
SFREG f26,( 26 + 32)*REGBYTES(sp)
|
||||
SFREG f27,( 27 + 32)*REGBYTES(sp)
|
||||
SFREG f28,( 28 + 32)*REGBYTES(sp)
|
||||
SFREG f29,( 29 + 32)*REGBYTES(sp)
|
||||
SFREG f30,( 30 + 32)*REGBYTES(sp)
|
||||
SFREG f31,( 31 + 32)*REGBYTES(sp)
|
||||
|
||||
csrr a0, mcause
|
||||
csrr a1, mepc
|
||||
mv a2, sp
|
||||
add a3, sp, 32*REGBYTES
|
||||
bgez a0, .handle_syscall
|
||||
.handle_irq:
|
||||
jal handle_irq
|
||||
j .restore
|
||||
.handle_syscall:
|
||||
jal handle_syscall
|
||||
.restore:
|
||||
csrw mepc, a0
|
||||
LREG x1, 1*REGBYTES(sp)
|
||||
LREG x2, 2*REGBYTES(sp)
|
||||
LREG x3, 3*REGBYTES(sp)
|
||||
LREG x4, 4*REGBYTES(sp)
|
||||
LREG x5, 5*REGBYTES(sp)
|
||||
LREG x6, 6*REGBYTES(sp)
|
||||
LREG x7, 7*REGBYTES(sp)
|
||||
LREG x8, 8*REGBYTES(sp)
|
||||
LREG x9, 9*REGBYTES(sp)
|
||||
LREG x10, 10*REGBYTES(sp)
|
||||
LREG x11, 11*REGBYTES(sp)
|
||||
LREG x12, 12*REGBYTES(sp)
|
||||
LREG x13, 13*REGBYTES(sp)
|
||||
LREG x14, 14*REGBYTES(sp)
|
||||
LREG x15, 15*REGBYTES(sp)
|
||||
LREG x16, 16*REGBYTES(sp)
|
||||
LREG x17, 17*REGBYTES(sp)
|
||||
LREG x18, 18*REGBYTES(sp)
|
||||
LREG x19, 19*REGBYTES(sp)
|
||||
LREG x20, 20*REGBYTES(sp)
|
||||
LREG x21, 21*REGBYTES(sp)
|
||||
LREG x22, 22*REGBYTES(sp)
|
||||
LREG x23, 23*REGBYTES(sp)
|
||||
LREG x24, 24*REGBYTES(sp)
|
||||
LREG x25, 25*REGBYTES(sp)
|
||||
LREG x26, 26*REGBYTES(sp)
|
||||
LREG x27, 27*REGBYTES(sp)
|
||||
LREG x28, 28*REGBYTES(sp)
|
||||
LREG x29, 29*REGBYTES(sp)
|
||||
LREG x30, 30*REGBYTES(sp)
|
||||
LREG x31, 31*REGBYTES(sp)
|
||||
|
||||
LFREG f0, ( 0 + 32)*REGBYTES(sp)
|
||||
LFREG f1, ( 1 + 32)*REGBYTES(sp)
|
||||
LFREG f2, ( 2 + 32)*REGBYTES(sp)
|
||||
LFREG f3, ( 3 + 32)*REGBYTES(sp)
|
||||
LFREG f4, ( 4 + 32)*REGBYTES(sp)
|
||||
LFREG f5, ( 5 + 32)*REGBYTES(sp)
|
||||
LFREG f6, ( 6 + 32)*REGBYTES(sp)
|
||||
LFREG f7, ( 7 + 32)*REGBYTES(sp)
|
||||
LFREG f8, ( 8 + 32)*REGBYTES(sp)
|
||||
LFREG f9, ( 9 + 32)*REGBYTES(sp)
|
||||
LFREG f10,( 10 + 32)*REGBYTES(sp)
|
||||
LFREG f11,( 11 + 32)*REGBYTES(sp)
|
||||
LFREG f12,( 12 + 32)*REGBYTES(sp)
|
||||
LFREG f13,( 13 + 32)*REGBYTES(sp)
|
||||
LFREG f14,( 14 + 32)*REGBYTES(sp)
|
||||
LFREG f15,( 15 + 32)*REGBYTES(sp)
|
||||
LFREG f16,( 16 + 32)*REGBYTES(sp)
|
||||
LFREG f17,( 17 + 32)*REGBYTES(sp)
|
||||
LFREG f18,( 18 + 32)*REGBYTES(sp)
|
||||
LFREG f19,( 19 + 32)*REGBYTES(sp)
|
||||
LFREG f20,( 20 + 32)*REGBYTES(sp)
|
||||
LFREG f21,( 21 + 32)*REGBYTES(sp)
|
||||
LFREG f22,( 22 + 32)*REGBYTES(sp)
|
||||
LFREG f23,( 23 + 32)*REGBYTES(sp)
|
||||
LFREG f24,( 24 + 32)*REGBYTES(sp)
|
||||
LFREG f25,( 25 + 32)*REGBYTES(sp)
|
||||
LFREG f26,( 26 + 32)*REGBYTES(sp)
|
||||
LFREG f27,( 27 + 32)*REGBYTES(sp)
|
||||
LFREG f28,( 28 + 32)*REGBYTES(sp)
|
||||
LFREG f29,( 29 + 32)*REGBYTES(sp)
|
||||
LFREG f30,( 30 + 32)*REGBYTES(sp)
|
||||
LFREG f31,( 31 + 32)*REGBYTES(sp)
|
||||
|
||||
addi sp, sp, 64*REGBYTES
|
||||
mret
|
||||
|
||||
.section ".tdata.begin"
|
||||
.globl _tdata_begin
|
||||
_tdata_begin:
|
||||
|
||||
.section ".tdata.end"
|
||||
.globl _tdata_end
|
||||
_tdata_end:
|
||||
|
||||
.section ".tbss.end"
|
||||
.globl _tbss_end
|
||||
_tbss_end:
|
||||
|
||||
@@ -1,37 +0,0 @@
|
||||
/* Copyright 2018 Canaan Inc.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* http://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.
|
||||
*/
|
||||
|
||||
#include "entry.h"
|
||||
|
||||
/**
|
||||
* @brief Dummy function for __libc_init_array called
|
||||
*/
|
||||
void __attribute__((weak)) _init(void)
|
||||
{
|
||||
/**
|
||||
* These don't have to do anything since we use init_array/fini_array.
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Dummy function for __libc_fini_array called
|
||||
*/
|
||||
void __attribute__((weak)) _fini(void)
|
||||
{
|
||||
/**
|
||||
* These don't have to do anything since we use init_array/fini_array.
|
||||
*/
|
||||
}
|
||||
|
||||
@@ -1,102 +0,0 @@
|
||||
/* Copyright 2018 Canaan Inc.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* http://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.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "atomic.h"
|
||||
#include "clint.h"
|
||||
#include "dmac.h"
|
||||
#include "entry.h"
|
||||
#include "fpioa.h"
|
||||
#include "platform.h"
|
||||
#include "plic.h"
|
||||
#include "sysctl.h"
|
||||
#include "syslog.h"
|
||||
#include "uarths.h"
|
||||
|
||||
extern volatile uint64_t g_wake_up[2];
|
||||
|
||||
core_instance_t core1_instance;
|
||||
|
||||
volatile char * const ram = (volatile char*)RAM_BASE_ADDR;
|
||||
|
||||
extern char _heap_start[];
|
||||
extern char _heap_end[];
|
||||
|
||||
void thread_entry(int core_id)
|
||||
{
|
||||
while (!atomic_read(&g_wake_up[core_id]));
|
||||
}
|
||||
|
||||
void core_enable(int core_id)
|
||||
{
|
||||
clint_ipi_send(core_id);
|
||||
atomic_set(&g_wake_up[core_id], 1);
|
||||
}
|
||||
|
||||
int register_core1(core_function func, void *ctx)
|
||||
{
|
||||
if(func == NULL)
|
||||
return -1;
|
||||
core1_instance.callback = func;
|
||||
core1_instance.ctx = ctx;
|
||||
core_enable(1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int __attribute__((weak)) os_entry(int core_id, int number_of_cores, int (*user_main)(int, char**))
|
||||
{
|
||||
/* Call main if there is no OS */
|
||||
return user_main(0, 0);
|
||||
}
|
||||
|
||||
void _init_bsp(int core_id, int number_of_cores)
|
||||
{
|
||||
extern int main(int argc, char* argv[]);
|
||||
extern void __libc_init_array(void);
|
||||
extern void __libc_fini_array(void);
|
||||
|
||||
if (core_id == 0)
|
||||
{
|
||||
/* Initialize bss data to 0 */
|
||||
init_bss();
|
||||
/* Init UART */
|
||||
uarths_init();
|
||||
/* Init FPIOA */
|
||||
fpioa_init();
|
||||
/* Register finalization function */
|
||||
atexit(__libc_fini_array);
|
||||
/* Init libc array for C++ */
|
||||
__libc_init_array();
|
||||
/* Get reset status */
|
||||
sysctl_get_reset_status();
|
||||
}
|
||||
|
||||
int ret = 0;
|
||||
if (core_id == 0)
|
||||
{
|
||||
core1_instance.callback = NULL;
|
||||
core1_instance.ctx = NULL;
|
||||
ret = os_entry(core_id, number_of_cores, main);
|
||||
}
|
||||
else
|
||||
{
|
||||
thread_entry(core_id);
|
||||
if(core1_instance.callback == NULL)
|
||||
asm volatile ("wfi");
|
||||
else
|
||||
ret = core1_instance.callback(core1_instance.ctx);
|
||||
}
|
||||
exit(ret);
|
||||
}
|
||||
@@ -1,243 +0,0 @@
|
||||
|
||||
/* Copyright 2018 Canaan Inc.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* http://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 _BSP_ATOMIC_H
|
||||
#define _BSP_ATOMIC_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
#define SPINLOCK_INIT \
|
||||
{ \
|
||||
0 \
|
||||
}
|
||||
|
||||
#define CORELOCK_INIT \
|
||||
{ \
|
||||
.lock = SPINLOCK_INIT, \
|
||||
.count = 0, \
|
||||
.core = -1 \
|
||||
}
|
||||
|
||||
|
||||
/* Defination of memory barrier macro */
|
||||
#define mb() \
|
||||
{ \
|
||||
asm volatile("fence" :: \
|
||||
: "memory"); \
|
||||
}
|
||||
|
||||
#define atomic_set(ptr, val) (*(volatile typeof(*(ptr))*)(ptr) = val)
|
||||
#define atomic_read(ptr) (*(volatile typeof(*(ptr))*)(ptr))
|
||||
|
||||
#ifndef __riscv_atomic
|
||||
#error "atomic extension is required."
|
||||
#endif
|
||||
#define atomic_add(ptr, inc) __sync_fetch_and_add(ptr, inc)
|
||||
#define atomic_or(ptr, inc) __sync_fetch_and_or(ptr, inc)
|
||||
#define atomic_swap(ptr, swp) __sync_lock_test_and_set(ptr, swp)
|
||||
#define atomic_cas(ptr, cmp, swp) __sync_val_compare_and_swap(ptr, cmp, swp)
|
||||
|
||||
typedef struct _spinlock
|
||||
{
|
||||
int lock;
|
||||
} spinlock_t;
|
||||
|
||||
typedef struct _semaphore
|
||||
{
|
||||
spinlock_t lock;
|
||||
int count;
|
||||
int waiting;
|
||||
} semaphore_t;
|
||||
|
||||
|
||||
typedef struct _corelock
|
||||
{
|
||||
spinlock_t lock;
|
||||
int count;
|
||||
int core;
|
||||
} corelock_t;
|
||||
|
||||
static inline int spinlock_trylock(spinlock_t *lock)
|
||||
{
|
||||
int res = atomic_swap(&lock->lock, -1);
|
||||
/* Use memory barrier to keep coherency */
|
||||
mb();
|
||||
return res;
|
||||
}
|
||||
|
||||
static inline void spinlock_lock(spinlock_t *lock)
|
||||
{
|
||||
while (spinlock_trylock(lock));
|
||||
}
|
||||
|
||||
static inline void spinlock_unlock(spinlock_t *lock)
|
||||
{
|
||||
/* Use memory barrier to keep coherency */
|
||||
mb();
|
||||
atomic_set(&lock->lock, 0);
|
||||
asm volatile ("nop");
|
||||
}
|
||||
|
||||
static inline void semaphore_signal(semaphore_t *semaphore, int i)
|
||||
{
|
||||
spinlock_lock(&(semaphore->lock));
|
||||
semaphore->count += i;
|
||||
spinlock_unlock(&(semaphore->lock));
|
||||
}
|
||||
|
||||
static inline void semaphore_wait(semaphore_t *semaphore, int i)
|
||||
{
|
||||
atomic_add(&(semaphore->waiting), 1);
|
||||
while (1)
|
||||
{
|
||||
spinlock_lock(&(semaphore->lock));
|
||||
if (semaphore->count >= i)
|
||||
{
|
||||
semaphore->count -= i;
|
||||
atomic_add(&(semaphore->waiting), -1);
|
||||
spinlock_unlock(&(semaphore->lock));
|
||||
break;
|
||||
}
|
||||
spinlock_unlock(&(semaphore->lock));
|
||||
}
|
||||
}
|
||||
|
||||
static inline int semaphore_count(semaphore_t *semaphore)
|
||||
{
|
||||
int res = 0;
|
||||
|
||||
spinlock_lock(&(semaphore->lock));
|
||||
res = semaphore->count;
|
||||
spinlock_unlock(&(semaphore->lock));
|
||||
return res;
|
||||
}
|
||||
|
||||
static inline int semaphore_waiting(semaphore_t *semaphore)
|
||||
{
|
||||
return atomic_read(&(semaphore->waiting));
|
||||
}
|
||||
|
||||
static inline int corelock_trylock(corelock_t *lock)
|
||||
{
|
||||
int res = 0;
|
||||
unsigned long core;
|
||||
|
||||
asm volatile("csrr %0, mhartid;"
|
||||
: "=r"(core));
|
||||
if(spinlock_trylock(&lock->lock))
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (lock->count == 0)
|
||||
{
|
||||
/* First time get lock */
|
||||
lock->count++;
|
||||
lock->core = core;
|
||||
res = 0;
|
||||
}
|
||||
else if (lock->core == core)
|
||||
{
|
||||
/* Same core get lock */
|
||||
lock->count++;
|
||||
res = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Different core get lock */
|
||||
res = -1;
|
||||
}
|
||||
spinlock_unlock(&lock->lock);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static inline void corelock_lock(corelock_t *lock)
|
||||
{
|
||||
unsigned long core;
|
||||
|
||||
asm volatile("csrr %0, mhartid;"
|
||||
: "=r"(core));
|
||||
spinlock_lock(&lock->lock);
|
||||
|
||||
if (lock->count == 0)
|
||||
{
|
||||
/* First time get lock */
|
||||
lock->count++;
|
||||
lock->core = core;
|
||||
}
|
||||
else if (lock->core == core)
|
||||
{
|
||||
/* Same core get lock */
|
||||
lock->count++;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Different core get lock */
|
||||
spinlock_unlock(&lock->lock);
|
||||
|
||||
do
|
||||
{
|
||||
while (atomic_read(&lock->count))
|
||||
;
|
||||
} while (corelock_trylock(lock));
|
||||
}
|
||||
spinlock_unlock(&lock->lock);
|
||||
}
|
||||
|
||||
static inline void corelock_unlock(corelock_t *lock)
|
||||
{
|
||||
unsigned long core;
|
||||
|
||||
asm volatile("csrr %0, mhartid;"
|
||||
: "=r"(core));
|
||||
spinlock_lock(&lock->lock);
|
||||
|
||||
if (lock->core == core)
|
||||
{
|
||||
/* Same core release lock */
|
||||
lock->count--;
|
||||
if (lock->count <= 0)
|
||||
{
|
||||
lock->core = -1;
|
||||
lock->count = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Different core release lock */
|
||||
spinlock_unlock(&lock->lock);
|
||||
|
||||
register unsigned long a7 asm("a7") = 93;
|
||||
register unsigned long a0 asm("a0") = 0;
|
||||
register unsigned long a1 asm("a1") = 0;
|
||||
register unsigned long a2 asm("a2") = 0;
|
||||
|
||||
asm volatile("scall"
|
||||
: "+r"(a0)
|
||||
: "r"(a1), "r"(a2), "r"(a7));
|
||||
}
|
||||
spinlock_unlock(&lock->lock);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _BSP_ATOMIC_H */
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
#ifndef _KENDRYTE_BSP_H
|
||||
#define _KENDRYTE_BSP_H
|
||||
#include "atomic.h"
|
||||
#include "entry.h"
|
||||
#include "sleep.h"
|
||||
#include "encoding.h"
|
||||
#endif
|
||||
@@ -1,141 +0,0 @@
|
||||
/* Copyright 2018 Canaan Inc.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* http://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 _BSP_DUMP_H
|
||||
#define _BSP_DUMP_H
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "syslog.h"
|
||||
#include "uarths.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define DUMP_PRINTF printk
|
||||
|
||||
static inline void
|
||||
dump_core(const char *reason, uintptr_t cause, uintptr_t epc, uintptr_t regs[32], uintptr_t fregs[32])
|
||||
{
|
||||
static const char *const reg_usage[][2] =
|
||||
{
|
||||
{"zero ", "Hard-wired zero"},
|
||||
{"ra ", "Return address"},
|
||||
{"sp ", "Stack pointer"},
|
||||
{"gp ", "Global pointer"},
|
||||
{"tp ", "Thread pointer"},
|
||||
{"t0 ", "Temporaries Caller"},
|
||||
{"t1 ", "Temporaries Caller"},
|
||||
{"t2 ", "Temporaries Caller"},
|
||||
{"s0/fp", "Saved register/frame pointer"},
|
||||
{"s1 ", "Saved register"},
|
||||
{"a0 ", "Function arguments/return values"},
|
||||
{"a1 ", "Function arguments/return values"},
|
||||
{"a2 ", "Function arguments values"},
|
||||
{"a3 ", "Function arguments values"},
|
||||
{"a4 ", "Function arguments values"},
|
||||
{"a5 ", "Function arguments values"},
|
||||
{"a6 ", "Function arguments values"},
|
||||
{"a7 ", "Function arguments values"},
|
||||
{"s2 ", "Saved registers"},
|
||||
{"s3 ", "Saved registers"},
|
||||
{"s4 ", "Saved registers"},
|
||||
{"s5 ", "Saved registers"},
|
||||
{"s6 ", "Saved registers"},
|
||||
{"s7 ", "Saved registers"},
|
||||
{"s8 ", "Saved registers"},
|
||||
{"s9 ", "Saved registers"},
|
||||
{"s10 ", "Saved registers"},
|
||||
{"s11 ", "Saved registers"},
|
||||
{"t3 ", "Temporaries Caller"},
|
||||
{"t4 ", "Temporaries Caller"},
|
||||
{"t5 ", "Temporaries Caller"},
|
||||
{"t6 ", "Temporaries Caller"},
|
||||
};
|
||||
|
||||
static const char *const regf_usage[][2] =
|
||||
{
|
||||
{"ft0 ", "FP temporaries"},
|
||||
{"ft1 ", "FP temporaries"},
|
||||
{"ft2 ", "FP temporaries"},
|
||||
{"ft3 ", "FP temporaries"},
|
||||
{"ft4 ", "FP temporaries"},
|
||||
{"ft5 ", "FP temporaries"},
|
||||
{"ft6 ", "FP temporaries"},
|
||||
{"ft7 ", "FP temporaries"},
|
||||
{"fs0 ", "FP saved registers"},
|
||||
{"fs1 ", "FP saved registers"},
|
||||
{"fa0 ", "FP arguments/return values"},
|
||||
{"fa1 ", "FP arguments/return values"},
|
||||
{"fa2 ", "FP arguments values"},
|
||||
{"fa3 ", "FP arguments values"},
|
||||
{"fa4 ", "FP arguments values"},
|
||||
{"fa5 ", "FP arguments values"},
|
||||
{"fa6 ", "FP arguments values"},
|
||||
{"fa7 ", "FP arguments values"},
|
||||
{"fs2 ", "FP Saved registers"},
|
||||
{"fs3 ", "FP Saved registers"},
|
||||
{"fs4 ", "FP Saved registers"},
|
||||
{"fs5 ", "FP Saved registers"},
|
||||
{"fs6 ", "FP Saved registers"},
|
||||
{"fs7 ", "FP Saved registers"},
|
||||
{"fs8 ", "FP Saved registers"},
|
||||
{"fs9 ", "FP Saved registers"},
|
||||
{"fs10", "FP Saved registers"},
|
||||
{"fs11", "FP Saved registers"},
|
||||
{"ft8 ", "FP Temporaries Caller"},
|
||||
{"ft9 ", "FP Temporaries Caller"},
|
||||
{"ft10", "FP Temporaries Caller"},
|
||||
{"ft11", "FP Temporaries Caller"},
|
||||
};
|
||||
|
||||
if (CONFIG_LOG_LEVEL >= LOG_ERROR)
|
||||
{
|
||||
const char unknown_reason[] = "unknown";
|
||||
|
||||
if (!reason)
|
||||
reason = unknown_reason;
|
||||
|
||||
DUMP_PRINTF("core dump: %s\r\n", reason);
|
||||
DUMP_PRINTF("Cause 0x%016lx, EPC 0x%016lx\r\n", cause, epc);
|
||||
|
||||
int i = 0;
|
||||
for (i = 0; i < 32 / 2; i++)
|
||||
{
|
||||
DUMP_PRINTF(
|
||||
"reg[%02d](%s) = 0x%016lx, reg[%02d](%s) = 0x%016lx\r\n",
|
||||
i * 2, reg_usage[i * 2][0], regs[i * 2],
|
||||
i * 2 + 1, reg_usage[i * 2 + 1][0], regs[i * 2 + 1]);
|
||||
}
|
||||
|
||||
for (i = 0; i < 32 / 2; i++)
|
||||
{
|
||||
DUMP_PRINTF(
|
||||
"freg[%02d](%s) = 0x%016lx(%f), freg[%02d](%s) = 0x%016lx(%f)\r\n",
|
||||
i * 2, regf_usage[i * 2][0], fregs[i * 2], (float)fregs[i * 2],
|
||||
i * 2 + 1, regf_usage[i * 2 + 1][0], fregs[i * 2 + 1], (float)fregs[i * 2 + 1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#undef DUMP_PRINTF
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _BSP_DUMP_H */
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,81 +0,0 @@
|
||||
/* Copyright 2018 Canaan Inc.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* http://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 _BSP_ENTRY_H
|
||||
#define _BSP_ENTRY_H
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef int (*core_function)(void *ctx);
|
||||
|
||||
typedef struct _core_instance_t
|
||||
{
|
||||
core_function callback;
|
||||
void *ctx;
|
||||
} core_instance_t;
|
||||
|
||||
int register_core1(core_function func, void *ctx);
|
||||
|
||||
static inline void init_lma(void)
|
||||
{
|
||||
extern unsigned int _data_lma;
|
||||
extern unsigned int _data;
|
||||
extern unsigned int _edata;
|
||||
unsigned int *src, *dst;
|
||||
|
||||
src = &_data_lma;
|
||||
dst = &_data;
|
||||
while (dst < &_edata)
|
||||
*dst++ = *src++;
|
||||
}
|
||||
|
||||
static inline void init_bss(void)
|
||||
{
|
||||
extern unsigned int _bss;
|
||||
extern unsigned int _ebss;
|
||||
unsigned int *dst;
|
||||
|
||||
dst = &_bss;
|
||||
while (dst < &_ebss)
|
||||
*dst++ = 0;
|
||||
}
|
||||
|
||||
static inline void init_tls(void)
|
||||
{
|
||||
register void *thread_pointer asm("tp");
|
||||
extern char _tls_data;
|
||||
|
||||
extern __thread char _tdata_begin, _tdata_end, _tbss_end;
|
||||
|
||||
size_t tdata_size = &_tdata_end - &_tdata_begin;
|
||||
|
||||
memcpy(thread_pointer, &_tls_data, tdata_size);
|
||||
|
||||
size_t tbss_size = &_tbss_end - &_tdata_end;
|
||||
|
||||
memset(thread_pointer + tdata_size, 0, tbss_size);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _BSP_ENTRY_H */
|
||||
|
||||
@@ -1,47 +0,0 @@
|
||||
/* Copyright 2018 Canaan Inc.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* http://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 _BSP_INTERRUPT_H
|
||||
#define _BSP_INTERRUPT_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
/* clang-format off */
|
||||
/* Machine interrupt mask for 64 bit system, 0x8000 0000 0000 0000 */
|
||||
#define CAUSE_MACHINE_IRQ_MASK (0x1ULL << 63)
|
||||
|
||||
/* Machine interrupt reason mask for 64 bit system, 0x7FFF FFFF FFFF FFFF */
|
||||
#define CAUSE_MACHINE_IRQ_REASON_MASK (CAUSE_MACHINE_IRQ_MASK - 1)
|
||||
|
||||
/* Hypervisor interrupt mask for 64 bit system, 0x8000 0000 0000 0000 */
|
||||
#define CAUSE_HYPERVISOR_IRQ_MASK (0x1ULL << 63)
|
||||
|
||||
/* Hypervisor interrupt reason mask for 64 bit system, 0x7FFF FFFF FFFF FFFF */
|
||||
#define CAUSE_HYPERVISOR_IRQ_REASON_MASK (CAUSE_HYPERVISOR_IRQ_MASK - 1)
|
||||
|
||||
/* Supervisor interrupt mask for 64 bit system, 0x8000 0000 0000 0000 */
|
||||
#define CAUSE_SUPERVISOR_IRQ_MASK (0x1ULL << 63)
|
||||
|
||||
/* Supervisor interrupt reason mask for 64 bit system, 0x7FFF FFFF FFFF FFFF */
|
||||
#define CAUSE_SUPERVISOR_IRQ_REASON_MASK (CAUSE_SUPERVISOR_IRQ_MASK - 1)
|
||||
/* clang-format on */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _BSP_INTERRUPT_H */
|
||||
|
||||
@@ -1,99 +0,0 @@
|
||||
/* Copyright 2018 Canaan Inc.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* http://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 _BSP_PLATFORM_H
|
||||
#define _BSP_PLATFORM_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* clang-format off */
|
||||
/* Register base address */
|
||||
|
||||
/* Under Coreplex */
|
||||
#define CLINT_BASE_ADDR (0x02000000U)
|
||||
#define PLIC_BASE_ADDR (0x0C000000U)
|
||||
|
||||
/* Under TileLink */
|
||||
#define UARTHS_BASE_ADDR (0x38000000U)
|
||||
#define GPIOHS_BASE_ADDR (0x38001000U)
|
||||
|
||||
/* Under AXI 64 bit */
|
||||
#define RAM_BASE_ADDR (0x80000000U)
|
||||
#define RAM_SIZE (6 * 1024 * 1024U)
|
||||
|
||||
#define IO_BASE_ADDR (0x40000000U)
|
||||
#define IO_SIZE (6 * 1024 * 1024U)
|
||||
|
||||
#define AI_RAM_BASE_ADDR (0x80600000U)
|
||||
#define AI_RAM_SIZE (2 * 1024 * 1024U)
|
||||
|
||||
#define AI_IO_BASE_ADDR (0x40600000U)
|
||||
#define AI_IO_SIZE (2 * 1024 * 1024U)
|
||||
|
||||
#define AI_BASE_ADDR (0x40800000U)
|
||||
#define AI_SIZE (12 * 1024 * 1024U)
|
||||
|
||||
#define FFT_BASE_ADDR (0x42000000U)
|
||||
#define FFT_SIZE (4 * 1024 * 1024U)
|
||||
|
||||
#define ROM_BASE_ADDR (0x88000000U)
|
||||
#define ROM_SIZE (128 * 1024U)
|
||||
|
||||
/* Under AHB 32 bit */
|
||||
#define DMAC_BASE_ADDR (0x50000000U)
|
||||
|
||||
/* Under APB1 32 bit */
|
||||
#define GPIO_BASE_ADDR (0x50200000U)
|
||||
#define UART1_BASE_ADDR (0x50210000U)
|
||||
#define UART2_BASE_ADDR (0x50220000U)
|
||||
#define UART3_BASE_ADDR (0x50230000U)
|
||||
#define SPI_SLAVE_BASE_ADDR (0x50240000U)
|
||||
#define I2S0_BASE_ADDR (0x50250000U)
|
||||
#define I2S1_BASE_ADDR (0x50260000U)
|
||||
#define I2S2_BASE_ADDR (0x50270000U)
|
||||
#define I2C0_BASE_ADDR (0x50280000U)
|
||||
#define I2C1_BASE_ADDR (0x50290000U)
|
||||
#define I2C2_BASE_ADDR (0x502A0000U)
|
||||
#define FPIOA_BASE_ADDR (0x502B0000U)
|
||||
#define SHA256_BASE_ADDR (0x502C0000U)
|
||||
#define TIMER0_BASE_ADDR (0x502D0000U)
|
||||
#define TIMER1_BASE_ADDR (0x502E0000U)
|
||||
#define TIMER2_BASE_ADDR (0x502F0000U)
|
||||
|
||||
/* Under APB2 32 bit */
|
||||
#define WDT0_BASE_ADDR (0x50400000U)
|
||||
#define WDT1_BASE_ADDR (0x50410000U)
|
||||
#define OTP_BASE_ADDR (0x50420000U)
|
||||
#define DVP_BASE_ADDR (0x50430000U)
|
||||
#define SYSCTL_BASE_ADDR (0x50440000U)
|
||||
#define AES_BASE_ADDR (0x50450000U)
|
||||
#define RTC_BASE_ADDR (0x50460000U)
|
||||
|
||||
|
||||
/* Under APB3 32 bit */
|
||||
#define SPI0_BASE_ADDR (0x52000000U)
|
||||
#define SPI1_BASE_ADDR (0x53000000U)
|
||||
#define SPI3_BASE_ADDR (0x54000000U)
|
||||
|
||||
/* clang-format on */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _BSP_PLATFORM_H */
|
||||
|
||||
@@ -1,209 +0,0 @@
|
||||
/**
|
||||
* File: printf.h
|
||||
*
|
||||
* Copyright (c) 2004,2012 Kustaa Nyholm / SpareTimeLabs
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of Kustaa Nyholm or SpareTimeLabs 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 COPYRIGHT HOLDER 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.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this library; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* This library is really just two files: 'tinyprintf.h' and 'tinyprintf.c'.
|
||||
*
|
||||
* They provide a simple and small (+400 loc) printf functionality to be used
|
||||
* in embedded systems.
|
||||
*
|
||||
* I've found them so useful in debugging that I do not bother with a debugger
|
||||
* at all.
|
||||
*
|
||||
* They are distributed in source form, so to use them, just compile them into
|
||||
* your project.
|
||||
*
|
||||
* Two printf variants are provided: printf and the 'sprintf' family of
|
||||
* functions ('snprintf', 'sprintf', 'vsnprintf', 'vsprintf').
|
||||
*
|
||||
* The formats supported by this implementation are: 'c' 'd' 'i' 'o' 'p' 'u'
|
||||
* 's' 'x' 'X'.
|
||||
*
|
||||
* Zero padding, field width, and precision are also supported.
|
||||
*
|
||||
* If the library is compiled with 'PRINTF_SUPPORT_LONG' defined, then the
|
||||
* long specifier is also supported. Note that this will pull in some long
|
||||
* math routines (pun intended!) and thus make your executable noticeably
|
||||
* longer. Likewise with 'PRINTF_LONG_LONG_SUPPORT' for the long long
|
||||
* specifier, and with 'PRINTF_SIZE_T_SUPPORT' for the size_t specifier.
|
||||
*
|
||||
* The memory footprint of course depends on the target CPU, compiler and
|
||||
* compiler options, but a rough guesstimate (based on a H8S target) is about
|
||||
* 1.4 kB for code and some twenty 'int's and 'char's, say 60 bytes of stack
|
||||
* space. Not too bad. Your mileage may vary. By hacking the source code you
|
||||
* can get rid of some hundred bytes, I'm sure, but personally I feel the
|
||||
* balance of functionality and flexibility versus code size is close to
|
||||
* optimal for many embedded systems.
|
||||
*
|
||||
* To use the printf, you need to supply your own character output function,
|
||||
* something like :
|
||||
*
|
||||
* void putc ( void* p, char c) { while (!SERIAL_PORT_EMPTY) ;
|
||||
* SERIAL_PORT_TX_REGISTER = c; }
|
||||
*
|
||||
* Before you can call printf, you need to initialize it to use your character
|
||||
* output function with something like:
|
||||
*
|
||||
* init_printf(NULL,putc);
|
||||
*
|
||||
* Notice the 'NULL' in 'init_printf' and the parameter 'void* p' in 'putc',
|
||||
* the NULL (or any pointer) you pass into the 'init_printf' will eventually
|
||||
* be passed to your 'putc' routine. This allows you to pass some storage
|
||||
* space (or anything really) to the character output function, if necessary.
|
||||
* This is not often needed but it was implemented like that because it made
|
||||
* implementing the sprintf function so neat (look at the source code).
|
||||
*
|
||||
* The code is re-entrant, except for the 'init_printf' function, so it is
|
||||
* safe to call it from interrupts too, although this may result in mixed
|
||||
* output. If you rely on re-entrancy, take care that your 'putc' function is
|
||||
* re-entrant!
|
||||
*
|
||||
* The printf and sprintf functions are actually macros that translate to
|
||||
* 'tfp_printf' and 'tfp_sprintf' when 'TINYPRINTF_OVERRIDE_LIBC' is set
|
||||
* (default). Setting it to 0 makes it possible to use them along with
|
||||
* 'stdio.h' printf's in a single source file. When 'TINYPRINTF_OVERRIDE_LIBC'
|
||||
* is set, please note that printf/sprintf are not function-like macros, so if
|
||||
* you have variables or struct members with these names, things will explode
|
||||
* in your face. Without variadic macros this is the best we can do to wrap
|
||||
* these function. If it is a problem, just give up the macros and use the
|
||||
* functions directly, or rename them.
|
||||
*
|
||||
* It is also possible to avoid defining tfp_printf and/or tfp_sprintf by
|
||||
* clearing 'TINYPRINTF_DEFINE_TFP_PRINTF' and/or
|
||||
* 'TINYPRINTF_DEFINE_TFP_SPRINTF' to 0. This allows for example to export
|
||||
* only tfp_format, which is at the core of all the other functions.
|
||||
*
|
||||
* For further details see source code.
|
||||
*
|
||||
* regs Kusti, 23.10.2004
|
||||
*/
|
||||
|
||||
#ifndef _BSP_PRINTF_H
|
||||
#define _BSP_PRINTF_H
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stddef.h>
|
||||
|
||||
/* Global configuration */
|
||||
|
||||
/* Set this to 0 if you do not want to provide tfp_printf */
|
||||
#ifndef TINYPRINTF_DEFINE_TFP_PRINTF
|
||||
#define TINYPRINTF_DEFINE_TFP_PRINTF 1
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Set this to 0 if you do not want to provide
|
||||
* tfp_sprintf/snprintf/vsprintf/vsnprintf
|
||||
*/
|
||||
#ifndef TINYPRINTF_DEFINE_TFP_SPRINTF
|
||||
#define TINYPRINTF_DEFINE_TFP_SPRINTF 1
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Set this to 0 if you do not want tfp_printf and
|
||||
* tfp_{vsn,sn,vs,s}printf to be also available as
|
||||
* printf/{vsn,sn,vs,s}printf
|
||||
*/
|
||||
#ifndef TINYPRINTF_OVERRIDE_LIBC
|
||||
#define TINYPRINTF_OVERRIDE_LIBC 0
|
||||
#endif
|
||||
|
||||
/* Optional external types dependencies */
|
||||
|
||||
/* Declarations */
|
||||
|
||||
#if defined(__GNUC__)
|
||||
#define _TFP_SPECIFY_PRINTF_FMT(fmt_idx, arg1_idx) \
|
||||
__attribute__((format(printf, fmt_idx, arg1_idx)))
|
||||
#else
|
||||
#define _TFP_SPECIFY_PRINTF_FMT(fmt_idx, arg1_idx)
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef void (*putcf)(void*, char);
|
||||
|
||||
/**
|
||||
* 'tfp_format' really is the central function for all tinyprintf. For
|
||||
* each output character after formatting, the 'putf' callback is
|
||||
* called with 2 args:
|
||||
* - an arbitrary void* 'putp' param defined by the user and
|
||||
* passed unmodified from 'tfp_format',
|
||||
* - the character.
|
||||
* The 'tfp_printf' and 'tfp_sprintf' functions simply define their own
|
||||
* callback and pass to it the right 'putp' it is expecting.
|
||||
*/
|
||||
void tfp_format(void *putp, putcf putf, const char *fmt, va_list va);
|
||||
|
||||
#if TINYPRINTF_DEFINE_TFP_SPRINTF
|
||||
int tfp_vsnprintf(char *str, size_t size, const char *fmt, va_list ap);
|
||||
int tfp_snprintf(char *str, size_t size, const char *fmt, ...)
|
||||
_TFP_SPECIFY_PRINTF_FMT(3, 4);
|
||||
int tfp_vsprintf(char *str, const char *fmt, va_list ap);
|
||||
int tfp_sprintf(char *str, const char *fmt, ...) _TFP_SPECIFY_PRINTF_FMT(2, 3);
|
||||
#if TINYPRINTF_OVERRIDE_LIBC
|
||||
#define vsnprintf tfp_vsnprintf
|
||||
#define snprintf tfp_snprintf
|
||||
#define vsprintf tfp_vsprintf
|
||||
#define sprintf tfp_sprintf
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if TINYPRINTF_DEFINE_TFP_PRINTF
|
||||
void init_printf(void *putp, putcf putf);
|
||||
void tfp_printf(char *fmt, ...) _TFP_SPECIFY_PRINTF_FMT(1, 2);
|
||||
#if TINYPRINTF_OVERRIDE_LIBC
|
||||
#define printf tfp_printf
|
||||
|
||||
#ifdef __cplusplus
|
||||
#include <forward_list>
|
||||
namespace std
|
||||
{
|
||||
template <typename... Args>
|
||||
auto tfp_printf(Args&&... args) -> decltype(::tfp_printf(std::forward<Args>(args)...))
|
||||
{
|
||||
return ::tfp_printf(std::forward<Args>(args)...);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
int printk(const char *format, ...) _TFP_SPECIFY_PRINTF_FMT(1, 2);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _BSP_PRINTF_H */
|
||||
|
||||
@@ -1,36 +0,0 @@
|
||||
/* Copyright 2018 Canaan Inc.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* http://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 _BSP_SLEEP_H
|
||||
#define _BSP_SLEEP_H
|
||||
|
||||
#include "encoding.h"
|
||||
#include "clint.h"
|
||||
#include "syscalls.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
int usleep(uint64_t usec);
|
||||
int msleep(uint64_t msec);
|
||||
unsigned int sleep(unsigned int seconds);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _BSP_SLEEP_H */
|
||||
|
||||
@@ -1,46 +0,0 @@
|
||||
/* Copyright 2018 Canaan Inc.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* http://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 _BSP_SYSCALLS_H
|
||||
#define _BSP_SYSCALLS_H
|
||||
|
||||
#include <machine/syscall.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void __attribute__((noreturn)) sys_exit(int code);
|
||||
|
||||
void setStats(int enable);
|
||||
|
||||
#undef putchar
|
||||
int putchar(int ch);
|
||||
void printstr(const char *s);
|
||||
|
||||
void printhex(uint64_t x);
|
||||
|
||||
size_t get_free_heap_size(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _BSP_SYSCALLS_H */
|
||||
|
||||
@@ -1,198 +0,0 @@
|
||||
/* Copyright 2018 Canaan Inc.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* http://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 _BSP_UTIL_H
|
||||
#define _BSP_UTIL_H
|
||||
|
||||
|
||||
#include <stdint.h>
|
||||
#if defined(__riscv)
|
||||
#include "encoding.h"
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if defined(__GNUC__)
|
||||
#pragma GCC diagnostic ignored "-Wunused-parameter"
|
||||
#pragma GCC diagnostic ignored "-Wunused-function"
|
||||
#endif
|
||||
|
||||
/**
|
||||
* --------------------------------------------------------------------------
|
||||
* Macros
|
||||
|
||||
* Set HOST_DEBUG to 1 if you are going to compile this for a host
|
||||
* machine (ie Athena/Linux) for debug purposes and set HOST_DEBUG
|
||||
* to 0 if you are compiling with the smips-gcc toolchain.
|
||||
*/
|
||||
|
||||
#ifndef HOST_DEBUG
|
||||
#define HOST_DEBUG 0
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Set PREALLOCATE to 1 if you want to preallocate the benchmark
|
||||
* function before starting stats. If you have instruction/data
|
||||
* caches and you don't want to count the overhead of misses, then
|
||||
* you will need to use preallocation.
|
||||
*/
|
||||
|
||||
#ifndef PREALLOCATE
|
||||
#define PREALLOCATE 0
|
||||
#endif
|
||||
|
||||
|
||||
#define static_assert(cond) \
|
||||
{ \
|
||||
switch (0) \
|
||||
{ \
|
||||
case 0: \
|
||||
case !!(long)(cond):; \
|
||||
} \
|
||||
}
|
||||
|
||||
#define stringify_1(s) #s
|
||||
#define stringify(s) stringify_1(s)
|
||||
#define stats(code, iter) \
|
||||
do \
|
||||
{ \
|
||||
unsigned long _c = -read_cycle(), _i = -read_csr(minstret); \
|
||||
code; \
|
||||
_c += read_cycle(), _i += read_csr(minstret); \
|
||||
if (cid == 0) \
|
||||
printf("\r\n%s: %ld cycles, %ld.%ld cycles/iter, %ld.%ld CPI\r\n", \
|
||||
stringify(code), _c, _c / iter, 10 * _c / iter % 10, _c / _i, 10 * _c / _i % 10); \
|
||||
} while (0)
|
||||
|
||||
|
||||
/**
|
||||
* Set SET_STATS to 1 if you want to carve out the piece that actually
|
||||
* does the computation.
|
||||
*/
|
||||
|
||||
#if HOST_DEBUG
|
||||
#include <stdio.h>
|
||||
static void setStats(int enable) {}
|
||||
#else
|
||||
extern void setStats(int enable);
|
||||
#endif
|
||||
|
||||
|
||||
static void printArray(const char name[], int n, const int arr[])
|
||||
{
|
||||
#if HOST_DEBUG
|
||||
int i;
|
||||
|
||||
printf(" %10s :", name);
|
||||
for (i = 0; i < n; i++)
|
||||
printf(" %3d ", arr[i]);
|
||||
printf("\r\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
static void printDoubleArray(const char name[], int n, const double arr[])
|
||||
{
|
||||
#if HOST_DEBUG
|
||||
int i;
|
||||
|
||||
printf(" %10s :", name);
|
||||
for (i = 0; i < n; i++)
|
||||
printf(" %g ", arr[i]);
|
||||
printf("\r\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
static int verify(int n, const volatile int *test, const int *verify)
|
||||
{
|
||||
int i;
|
||||
/* Unrolled for faster verification */
|
||||
for (i = 0; i < n / 2 * 2; i += 2)
|
||||
{
|
||||
int t0 = test[i], t1 = test[i + 1];
|
||||
int v0 = verify[i], v1 = verify[i + 1];
|
||||
|
||||
if (t0 != v0)
|
||||
return i + 1;
|
||||
if (t1 != v1)
|
||||
return i + 2;
|
||||
}
|
||||
if (n % 2 != 0 && test[n - 1] != verify[n - 1])
|
||||
return n;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int verifyDouble(int n, const volatile double *test, const double *verify)
|
||||
{
|
||||
int i;
|
||||
/* Unrolled for faster verification */
|
||||
for (i = 0; i < n / 2 * 2; i += 2)
|
||||
{
|
||||
double t0 = test[i], t1 = test[i + 1];
|
||||
double v0 = verify[i], v1 = verify[i + 1];
|
||||
int eq1 = t0 == v0, eq2 = t1 == v1;
|
||||
|
||||
if (!(eq1 & eq2))
|
||||
return i + 1 + eq1;
|
||||
}
|
||||
if (n % 2 != 0 && test[n - 1] != verify[n - 1])
|
||||
return n;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __attribute__((noinline)) barrier(int ncores)
|
||||
{
|
||||
static volatile int sense = 0;
|
||||
static volatile int count = 0;
|
||||
|
||||
static __thread int threadsense;
|
||||
|
||||
__sync_synchronize();
|
||||
|
||||
threadsense = !threadsense;
|
||||
if (__sync_fetch_and_add(&count, 1) == ncores - 1)
|
||||
{
|
||||
count = 0;
|
||||
sense = threadsense;
|
||||
}
|
||||
else
|
||||
{
|
||||
while (sense != threadsense)
|
||||
;
|
||||
}
|
||||
|
||||
__sync_synchronize();
|
||||
}
|
||||
|
||||
static uint64_t lfsr(uint64_t x)
|
||||
{
|
||||
uint64_t bit = (x ^ (x >> 1)) & 1;
|
||||
|
||||
return (x >> 1) | (bit << 62);
|
||||
}
|
||||
|
||||
|
||||
#if defined(__GNUC__)
|
||||
#pragma GCC diagnostic warning "-Wunused-parameter"
|
||||
#pragma GCC diagnostic warning "-Wunused-function"
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _BSP_UTIL_H */
|
||||
|
||||
@@ -1,66 +0,0 @@
|
||||
/* Copyright 2018 Canaan Inc.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* http://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.
|
||||
*/
|
||||
|
||||
/* Enable kernel-mode log API */
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include "interrupt.h"
|
||||
#include "dump.h"
|
||||
#include "syscalls.h"
|
||||
#include "syslog.h"
|
||||
|
||||
uintptr_t __attribute__((weak))
|
||||
handle_irq_dummy(uintptr_t cause, uintptr_t epc, uintptr_t regs[32], uintptr_t fregs[32])
|
||||
{
|
||||
dump_core("unhandled interrupt", cause, epc, regs, fregs);
|
||||
sys_exit(1337);
|
||||
return epc;
|
||||
}
|
||||
|
||||
uintptr_t __attribute__((weak, alias("handle_irq_dummy")))
|
||||
handle_irq_m_soft(uintptr_t cause, uintptr_t epc, uintptr_t regs[32], uintptr_t fregs[32]);
|
||||
|
||||
uintptr_t __attribute__((weak, alias("handle_irq_dummy")))
|
||||
handle_irq_m_timer(uintptr_t cause, uintptr_t epc, uintptr_t regs[32], uintptr_t fregs[32]);
|
||||
|
||||
extern uintptr_t
|
||||
handle_irq_m_ext(uintptr_t cause, uintptr_t epc, uintptr_t regs[32], uintptr_t fregs[32]);
|
||||
|
||||
uintptr_t __attribute__((weak))
|
||||
handle_irq(uintptr_t cause, uintptr_t epc, uintptr_t regs[32], uintptr_t fregs[32])
|
||||
{
|
||||
#if defined(__GNUC__)
|
||||
#pragma GCC diagnostic ignored "-Woverride-init"
|
||||
#endif
|
||||
/* clang-format off */
|
||||
static uintptr_t (* const irq_table[])(
|
||||
uintptr_t cause,
|
||||
uintptr_t epc,
|
||||
uintptr_t regs[32],
|
||||
uintptr_t fregs[32]) =
|
||||
{
|
||||
[0 ... 14] = handle_irq_dummy,
|
||||
[IRQ_M_SOFT] = handle_irq_m_soft,
|
||||
[IRQ_M_TIMER] = handle_irq_m_timer,
|
||||
[IRQ_M_EXT] = handle_irq_m_ext,
|
||||
};
|
||||
/* clang-format on */
|
||||
#if defined(__GNUC__)
|
||||
#pragma GCC diagnostic warning "-Woverride-init"
|
||||
#endif
|
||||
return irq_table[cause & CAUSE_MACHINE_IRQ_REASON_MASK](cause, epc, regs, fregs);
|
||||
}
|
||||
|
||||
@@ -1,653 +0,0 @@
|
||||
/**
|
||||
* File: printf.c
|
||||
*
|
||||
* Copyright (c) 2004,2012 Kustaa Nyholm / SpareTimeLabs
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of Kustaa Nyholm or SpareTimeLabs 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 COPYRIGHT HOLDER 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 <stddef.h>
|
||||
#include "printf.h"
|
||||
#include "atomic.h"
|
||||
#include "uarths.h"
|
||||
|
||||
|
||||
/**
|
||||
* Configuration
|
||||
*/
|
||||
|
||||
/* Enable long int support */
|
||||
#define PRINTF_LONG_SUPPORT
|
||||
|
||||
/* Enable long long int support (implies long int support) */
|
||||
#define PRINTF_LONG_LONG_SUPPORT
|
||||
|
||||
/* Enable %z (size_t) support */
|
||||
#define PRINTF_SIZE_T_SUPPORT
|
||||
|
||||
/**
|
||||
* Configuration adjustments
|
||||
*/
|
||||
#if defined(PRINTF_LONG_LONG_SUPPORT)
|
||||
#define PRINTF_LONG_SUPPORT
|
||||
#endif
|
||||
|
||||
/* __SIZEOF_<type>__ defined at least by gcc */
|
||||
#if defined(__SIZEOF_POINTER__)
|
||||
#define SIZEOF_POINTER __SIZEOF_POINTER__
|
||||
#endif
|
||||
#if defined(__SIZEOF_LONG_LONG__)
|
||||
#define SIZEOF_LONG_LONG __SIZEOF_LONG_LONG__
|
||||
#endif
|
||||
#if defined(__SIZEOF_LONG__)
|
||||
#define SIZEOF_LONG __SIZEOF_LONG__
|
||||
#endif
|
||||
#if defined(__SIZEOF_INT__)
|
||||
#define SIZEOF_INT __SIZEOF_INT__
|
||||
#endif
|
||||
|
||||
#if defined(__GNUC__)
|
||||
#define _TFP_GCC_NO_INLINE_ __attribute__((noinline))
|
||||
#else
|
||||
#define _TFP_GCC_NO_INLINE_
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(PRINTF_LONG_SUPPORT)
|
||||
#define BF_MAX 20 /* long = 64b on some architectures */
|
||||
#else
|
||||
#define BF_MAX 10 /* int = 32b on some architectures */
|
||||
#endif
|
||||
|
||||
|
||||
#define IS_DIGIT(x) ((x) >= '0' && (x) <= '9')
|
||||
|
||||
/* Clear unused warnings for actually unused variables */
|
||||
#define UNUSED(x) (void)(x)
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Implementation
|
||||
*/
|
||||
struct param
|
||||
{
|
||||
char lz : 1; /* Leading zeros */
|
||||
char alt : 1; /* alternate form */
|
||||
char uc : 1; /* Upper case (for base16 only) */
|
||||
char align_left : 1; /* 0 == align right (default), 1 == align left */
|
||||
int width; /* field width */
|
||||
int prec; /* precision */
|
||||
char sign; /* The sign to display (if any) */
|
||||
unsigned int base; /* number base (e.g.: 8, 10, 16) */
|
||||
char *bf; /* Buffer to output */
|
||||
size_t bf_len; /* Buffer length */
|
||||
};
|
||||
|
||||
static corelock_t lock = CORELOCK_INIT;
|
||||
|
||||
|
||||
|
||||
#if defined(PRINTF_LONG_LONG_SUPPORT)
|
||||
static void _TFP_GCC_NO_INLINE_ ulli2a(unsigned long long int num, struct param *p)
|
||||
{
|
||||
unsigned long long int d = 1;
|
||||
char *bf = p->bf;
|
||||
if ((p->prec == 0) && (num == 0))
|
||||
return;
|
||||
while (num / d >= p->base)
|
||||
{
|
||||
d *= p->base;
|
||||
}
|
||||
while (d != 0)
|
||||
{
|
||||
int dgt = num / d;
|
||||
num %= d;
|
||||
d /= p->base;
|
||||
*bf++ = dgt + (dgt < 10 ? '0' : (p->uc ? 'A' : 'a') - 10);
|
||||
}
|
||||
p->bf_len = bf - p->bf;
|
||||
}
|
||||
|
||||
static void lli2a(long long int num, struct param *p)
|
||||
{
|
||||
if (num < 0)
|
||||
{
|
||||
num = -num;
|
||||
p->sign = '-';
|
||||
}
|
||||
ulli2a(num, p);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(PRINTF_LONG_SUPPORT)
|
||||
static void uli2a(unsigned long int num, struct param *p)
|
||||
{
|
||||
unsigned long int d = 1;
|
||||
char *bf = p->bf;
|
||||
if ((p->prec == 0) && (num == 0))
|
||||
return;
|
||||
while (num / d >= p->base)
|
||||
{
|
||||
d *= p->base;
|
||||
}
|
||||
while (d != 0)
|
||||
{
|
||||
int dgt = num / d;
|
||||
num %= d;
|
||||
d /= p->base;
|
||||
*bf++ = dgt + (dgt < 10 ? '0' : (p->uc ? 'A' : 'a') - 10);
|
||||
}
|
||||
p->bf_len = bf - p->bf;
|
||||
}
|
||||
|
||||
static void li2a(long num, struct param *p)
|
||||
{
|
||||
if (num < 0)
|
||||
{
|
||||
num = -num;
|
||||
p->sign = '-';
|
||||
}
|
||||
uli2a(num, p);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void ui2a(unsigned int num, struct param *p)
|
||||
{
|
||||
unsigned int d = 1;
|
||||
char *bf = p->bf;
|
||||
if ((p->prec == 0) && (num == 0))
|
||||
return;
|
||||
while (num / d >= p->base)
|
||||
{
|
||||
d *= p->base;
|
||||
}
|
||||
while (d != 0)
|
||||
{
|
||||
int dgt = num / d;
|
||||
num %= d;
|
||||
d /= p->base;
|
||||
*bf++ = dgt + (dgt < 10 ? '0' : (p->uc ? 'A' : 'a') - 10);
|
||||
}
|
||||
p->bf_len = bf - p->bf;
|
||||
}
|
||||
|
||||
static void i2a(int num, struct param *p)
|
||||
{
|
||||
if (num < 0)
|
||||
{
|
||||
num = -num;
|
||||
p->sign = '-';
|
||||
}
|
||||
ui2a(num, p);
|
||||
}
|
||||
|
||||
static int a2d(char ch)
|
||||
{
|
||||
if (IS_DIGIT(ch))
|
||||
return ch - '0';
|
||||
else if (ch >= 'a' && ch <= 'f')
|
||||
return ch - 'a' + 10;
|
||||
else if (ch >= 'A' && ch <= 'F')
|
||||
return ch - 'A' + 10;
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
static char a2u(char ch, const char **src, int base, unsigned int *nump)
|
||||
{
|
||||
const char *p = *src;
|
||||
unsigned int num = 0;
|
||||
int digit;
|
||||
while ((digit = a2d(ch)) >= 0)
|
||||
{
|
||||
if (digit > base)
|
||||
break;
|
||||
num = num * base + digit;
|
||||
ch = *p++;
|
||||
}
|
||||
*src = p;
|
||||
*nump = num;
|
||||
return ch;
|
||||
}
|
||||
|
||||
static void putchw(void *putp, putcf putf, struct param *p)
|
||||
{
|
||||
char ch;
|
||||
int width = p->width;
|
||||
int prec = p->prec;
|
||||
char *bf = p->bf;
|
||||
size_t bf_len = p->bf_len;
|
||||
|
||||
/* Number of filling characters */
|
||||
width -= bf_len;
|
||||
prec -= bf_len;
|
||||
if (p->sign)
|
||||
width--;
|
||||
if (p->alt && p->base == 16)
|
||||
width -= 2;
|
||||
else if (p->alt && p->base == 8)
|
||||
width--;
|
||||
if (prec > 0)
|
||||
width -= prec;
|
||||
|
||||
/* Fill with space to align to the right, before alternate or sign */
|
||||
if (!p->lz && !p->align_left)
|
||||
{
|
||||
while (width-- > 0)
|
||||
putf(putp, ' ');
|
||||
}
|
||||
|
||||
/* print sign */
|
||||
if (p->sign)
|
||||
putf(putp, p->sign);
|
||||
|
||||
/* Alternate */
|
||||
if (p->alt && p->base == 16)
|
||||
{
|
||||
putf(putp, '0');
|
||||
putf(putp, (p->uc ? 'X' : 'x'));
|
||||
}
|
||||
else if (p->alt && p->base == 8)
|
||||
{
|
||||
putf(putp, '0');
|
||||
}
|
||||
|
||||
/* Fill with zeros, after alternate or sign */
|
||||
while (prec-- > 0)
|
||||
putf(putp, '0');
|
||||
if (p->lz)
|
||||
{
|
||||
while (width-- > 0)
|
||||
putf(putp, '0');
|
||||
}
|
||||
|
||||
/* Put actual buffer */
|
||||
while ((bf_len-- > 0) && (ch = *bf++))
|
||||
putf(putp, ch);
|
||||
|
||||
/* Fill with space to align to the left, after string */
|
||||
if (!p->lz && p->align_left)
|
||||
{
|
||||
while (width-- > 0)
|
||||
putf(putp, ' ');
|
||||
}
|
||||
}
|
||||
|
||||
void tfp_format(void *putp, putcf putf, const char *fmt, va_list va)
|
||||
{
|
||||
struct param p;
|
||||
char bf[BF_MAX];
|
||||
char ch;
|
||||
|
||||
while ((ch = *(fmt++)))
|
||||
{
|
||||
if (ch != '%')
|
||||
{
|
||||
putf(putp, ch);
|
||||
}
|
||||
else
|
||||
{
|
||||
#if defined(PRINTF_LONG_SUPPORT)
|
||||
char lng = 0; /* 1 for long, 2 for long long */
|
||||
#endif
|
||||
/* Init parameter struct */
|
||||
p.lz = 0;
|
||||
p.alt = 0;
|
||||
p.uc = 0;
|
||||
p.align_left = 0;
|
||||
p.width = 0;
|
||||
p.prec = -1;
|
||||
p.sign = 0;
|
||||
p.bf = bf;
|
||||
p.bf_len = 0;
|
||||
|
||||
/* Flags */
|
||||
while ((ch = *(fmt++)))
|
||||
{
|
||||
switch (ch)
|
||||
{
|
||||
case '-':
|
||||
p.align_left = 1;
|
||||
continue;
|
||||
case '0':
|
||||
p.lz = 1;
|
||||
continue;
|
||||
case '#':
|
||||
p.alt = 1;
|
||||
continue;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (p.align_left)
|
||||
p.lz = 0;
|
||||
|
||||
/* Width */
|
||||
if (ch == '*')
|
||||
{
|
||||
ch = *(fmt++);
|
||||
p.width = va_arg(va, int);
|
||||
if (p.width < 0)
|
||||
{
|
||||
p.align_left = 1;
|
||||
p.width = -p.width;
|
||||
}
|
||||
}
|
||||
else if (IS_DIGIT(ch))
|
||||
{
|
||||
unsigned int width;
|
||||
ch = a2u(ch, &fmt, 10, &(width));
|
||||
p.width = width;
|
||||
}
|
||||
|
||||
/* Precision */
|
||||
if (ch == '.')
|
||||
{
|
||||
ch = *(fmt++);
|
||||
if (ch == '*')
|
||||
{
|
||||
int prec;
|
||||
ch = *(fmt++);
|
||||
prec = va_arg(va, int);
|
||||
if (prec < 0)
|
||||
/* act as if precision was
|
||||
* omitted */
|
||||
p.prec = -1;
|
||||
else
|
||||
p.prec = prec;
|
||||
}
|
||||
else if (IS_DIGIT(ch))
|
||||
{
|
||||
unsigned int prec;
|
||||
ch = a2u(ch, &fmt, 10, &(prec));
|
||||
p.prec = prec;
|
||||
}
|
||||
else
|
||||
{
|
||||
p.prec = 0;
|
||||
}
|
||||
}
|
||||
if (p.prec >= 0)
|
||||
/* precision causes zero pad to be ignored */
|
||||
p.lz = 0;
|
||||
|
||||
#if defined(PRINTF_SIZE_T_SUPPORT)
|
||||
#if defined(PRINTF_LONG_SUPPORT)
|
||||
if (ch == 'z')
|
||||
{
|
||||
ch = *(fmt++);
|
||||
if (sizeof(size_t) == sizeof(unsigned long int))
|
||||
lng = 1;
|
||||
#if defined(PRINTF_LONG_LONG_SUPPORT)
|
||||
else if (sizeof(size_t) == sizeof(unsigned long long int))
|
||||
lng = 2;
|
||||
#endif
|
||||
}
|
||||
else
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(PRINTF_LONG_SUPPORT)
|
||||
if (ch == 'l')
|
||||
{
|
||||
ch = *(fmt++);
|
||||
lng = 1;
|
||||
#if defined(PRINTF_LONG_LONG_SUPPORT)
|
||||
if (ch == 'l')
|
||||
{
|
||||
ch = *(fmt++);
|
||||
lng = 2;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
switch (ch)
|
||||
{
|
||||
case 0:
|
||||
goto abort;
|
||||
case 'u':
|
||||
p.base = 10;
|
||||
if (p.prec < 0)
|
||||
p.prec = 1;
|
||||
#if defined(PRINTF_LONG_SUPPORT)
|
||||
#if defined(PRINTF_LONG_LONG_SUPPORT)
|
||||
if (2 == lng)
|
||||
ulli2a(va_arg(va, unsigned long long int), &p);
|
||||
else
|
||||
#endif
|
||||
if (1 == lng)
|
||||
uli2a(va_arg(va, unsigned long int), &p);
|
||||
else
|
||||
#endif
|
||||
ui2a(va_arg(va, unsigned int), &p);
|
||||
putchw(putp, putf, &p);
|
||||
break;
|
||||
case 'd': /* No break */
|
||||
case 'i':
|
||||
p.base = 10;
|
||||
if (p.prec < 0)
|
||||
p.prec = 1;
|
||||
#if defined(PRINTF_LONG_SUPPORT)
|
||||
#if defined(PRINTF_LONG_LONG_SUPPORT)
|
||||
if (2 == lng)
|
||||
lli2a(va_arg(va, long long int), &p);
|
||||
else
|
||||
#endif
|
||||
if (1 == lng)
|
||||
li2a(va_arg(va, long int), &p);
|
||||
else
|
||||
#endif
|
||||
i2a(va_arg(va, int), &p);
|
||||
putchw(putp, putf, &p);
|
||||
break;
|
||||
#if defined(SIZEOF_POINTER)
|
||||
case 'p':
|
||||
p.alt = 1;
|
||||
#if defined(SIZEOF_INT) && SIZEOF_POINTER <= SIZEOF_INT
|
||||
lng = 0;
|
||||
#elif defined(SIZEOF_LONG) && SIZEOF_POINTER <= SIZEOF_LONG
|
||||
lng = 1;
|
||||
#elif defined(SIZEOF_LONG_LONG) && SIZEOF_POINTER <= SIZEOF_LONG_LONG
|
||||
lng = 2;
|
||||
#endif
|
||||
#endif
|
||||
/* No break */
|
||||
case 'x': /* No break */
|
||||
case 'X':
|
||||
p.base = 16;
|
||||
p.uc = (ch == 'X') ? 1 : 0;
|
||||
if (p.prec < 0)
|
||||
p.prec = 1;
|
||||
#if defined(PRINTF_LONG_SUPPORT)
|
||||
#if defined(PRINTF_LONG_LONG_SUPPORT)
|
||||
if (2 == lng)
|
||||
ulli2a(va_arg(va, unsigned long long int), &p);
|
||||
else
|
||||
#endif
|
||||
if (1 == lng)
|
||||
uli2a(va_arg(va, unsigned long int), &p);
|
||||
else
|
||||
#endif
|
||||
ui2a(va_arg(va, unsigned int), &p);
|
||||
putchw(putp, putf, &p);
|
||||
break;
|
||||
case 'o':
|
||||
p.base = 8;
|
||||
if (p.prec < 0)
|
||||
p.prec = 1;
|
||||
ui2a(va_arg(va, unsigned int), &p);
|
||||
putchw(putp, putf, &p);
|
||||
break;
|
||||
case 'c':
|
||||
putf(putp, (char)(va_arg(va, int)));
|
||||
break;
|
||||
case 's':
|
||||
{
|
||||
unsigned int prec = p.prec;
|
||||
char *b;
|
||||
p.bf = va_arg(va, char*);
|
||||
b = p.bf;
|
||||
while ((prec-- != 0) && *b++)
|
||||
{
|
||||
p.bf_len++;
|
||||
}
|
||||
p.prec = -1;
|
||||
putchw(putp, putf, &p);
|
||||
}
|
||||
break;
|
||||
case '%':
|
||||
putf(putp, ch);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
abort:;
|
||||
}
|
||||
|
||||
#if defined(TINYPRINTF_DEFINE_TFP_PRINTF)
|
||||
static putcf stdout_putf;
|
||||
static void *stdout_putp;
|
||||
|
||||
void init_printf(void *putp, putcf putf)
|
||||
{
|
||||
stdout_putf = putf;
|
||||
stdout_putp = putp;
|
||||
}
|
||||
|
||||
void tfp_printf(char *fmt, ...)
|
||||
{
|
||||
va_list va;
|
||||
va_start(va, fmt);
|
||||
tfp_format(stdout_putp, stdout_putf, fmt, va);
|
||||
va_end(va);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(TINYPRINTF_DEFINE_TFP_SPRINTF)
|
||||
struct _vsnprintf_putcf_data
|
||||
{
|
||||
size_t dest_capacity;
|
||||
char *dest;
|
||||
size_t num_chars;
|
||||
};
|
||||
|
||||
static void _vsnprintf_putcf(void *p, char c)
|
||||
{
|
||||
struct _vsnprintf_putcf_data *data = (struct _vsnprintf_putcf_data*)p;
|
||||
if (data->num_chars < data->dest_capacity)
|
||||
data->dest[data->num_chars] = c;
|
||||
data->num_chars++;
|
||||
}
|
||||
|
||||
int tfp_vsnprintf(char *str, size_t size, const char *format, va_list ap)
|
||||
{
|
||||
struct _vsnprintf_putcf_data data;
|
||||
|
||||
if (size < 1)
|
||||
return 0;
|
||||
|
||||
data.dest = str;
|
||||
data.dest_capacity = size - 1;
|
||||
data.num_chars = 0;
|
||||
tfp_format(&data, _vsnprintf_putcf, format, ap);
|
||||
|
||||
if (data.num_chars < data.dest_capacity)
|
||||
data.dest[data.num_chars] = '\0';
|
||||
else
|
||||
data.dest[data.dest_capacity] = '\0';
|
||||
|
||||
return data.num_chars;
|
||||
}
|
||||
|
||||
int tfp_snprintf(char *str, size_t size, const char *format, ...)
|
||||
{
|
||||
va_list ap;
|
||||
int retval;
|
||||
|
||||
va_start(ap, format);
|
||||
retval = tfp_vsnprintf(str, size, format, ap);
|
||||
va_end(ap);
|
||||
return retval;
|
||||
}
|
||||
|
||||
struct _vsprintf_putcf_data
|
||||
{
|
||||
char *dest;
|
||||
size_t num_chars;
|
||||
};
|
||||
|
||||
static void _vsprintf_putcf(void *p, char c)
|
||||
{
|
||||
struct _vsprintf_putcf_data *data = (struct _vsprintf_putcf_data*)p;
|
||||
data->dest[data->num_chars++] = c;
|
||||
}
|
||||
|
||||
int tfp_vsprintf(char *str, const char *format, va_list ap)
|
||||
{
|
||||
struct _vsprintf_putcf_data data;
|
||||
data.dest = str;
|
||||
data.num_chars = 0;
|
||||
tfp_format(&data, _vsprintf_putcf, format, ap);
|
||||
data.dest[data.num_chars] = '\0';
|
||||
return data.num_chars;
|
||||
}
|
||||
|
||||
int tfp_sprintf(char *str, const char *format, ...)
|
||||
{
|
||||
va_list ap;
|
||||
int retval;
|
||||
|
||||
va_start(ap, format);
|
||||
retval = tfp_vsprintf(str, format, ap);
|
||||
va_end(ap);
|
||||
return retval;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void uart_putf(void *unused, char c)
|
||||
{
|
||||
UNUSED(unused);
|
||||
uarths_putchar(c);
|
||||
}
|
||||
|
||||
int printk(const char *format, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, format);
|
||||
/* Begin protected code */
|
||||
corelock_lock(&lock);
|
||||
tfp_format(stdout_putp, uart_putf, format, ap);
|
||||
/* End protected code */
|
||||
corelock_unlock(&lock);
|
||||
va_end(ap);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1,39 +0,0 @@
|
||||
/* Copyright 2018 Canaan Inc.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* http://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.
|
||||
*/
|
||||
#include "sleep.h"
|
||||
#include "sysctl.h"
|
||||
|
||||
int usleep(uint64_t usec)
|
||||
{
|
||||
uint64_t cycle = read_cycle();
|
||||
uint64_t nop_all = usec * sysctl_clock_get_freq(SYSCTL_CLOCK_CPU) / 1000000UL;
|
||||
while (1)
|
||||
{
|
||||
if(read_cycle() - cycle >= nop_all)
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int msleep(uint64_t msec)
|
||||
{
|
||||
return (unsigned int)usleep(msec * 1000);
|
||||
}
|
||||
|
||||
unsigned int sleep(unsigned int seconds)
|
||||
{
|
||||
return (unsigned int)msleep(seconds * 1000);
|
||||
}
|
||||
|
||||
@@ -1,631 +0,0 @@
|
||||
/* Copyright 2018 Canaan Inc.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* http://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.
|
||||
*/
|
||||
|
||||
/* Enable kernel-mode log API */
|
||||
|
||||
#include <sys/stat.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/unistd.h>
|
||||
#include <machine/syscall.h>
|
||||
#include <stdbool.h>
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "syscalls.h"
|
||||
#include "atomic.h"
|
||||
#include "clint.h"
|
||||
#include "fpioa.h"
|
||||
#include "interrupt.h"
|
||||
#include "sysctl.h"
|
||||
#include "uarths.h"
|
||||
#include "util.h"
|
||||
#include "syslog.h"
|
||||
#include "dump.h"
|
||||
|
||||
/**
|
||||
* @note System call list
|
||||
*
|
||||
* See also riscv-newlib/libgloss/riscv/syscalls.c
|
||||
*
|
||||
* | System call | Number |
|
||||
* |------------------|--------|
|
||||
* | SYS_exit | 93 |
|
||||
* | SYS_exit_group | 94 |
|
||||
* | SYS_getpid | 172 |
|
||||
* | SYS_kill | 129 |
|
||||
* | SYS_read | 63 |
|
||||
* | SYS_write | 64 |
|
||||
* | SYS_open | 1024 |
|
||||
* | SYS_openat | 56 |
|
||||
* | SYS_close | 57 |
|
||||
* | SYS_lseek | 62 |
|
||||
* | SYS_brk | 214 |
|
||||
* | SYS_link | 1025 |
|
||||
* | SYS_unlink | 1026 |
|
||||
* | SYS_mkdir | 1030 |
|
||||
* | SYS_chdir | 49 |
|
||||
* | SYS_getcwd | 17 |
|
||||
* | SYS_stat | 1038 |
|
||||
* | SYS_fstat | 80 |
|
||||
* | SYS_lstat | 1039 |
|
||||
* | SYS_fstatat | 79 |
|
||||
* | SYS_access | 1033 |
|
||||
* | SYS_faccessat | 48 |
|
||||
* | SYS_pread | 67 |
|
||||
* | SYS_pwrite | 68 |
|
||||
* | SYS_uname | 160 |
|
||||
* | SYS_getuid | 174 |
|
||||
* | SYS_geteuid | 175 |
|
||||
* | SYS_getgid | 176 |
|
||||
* | SYS_getegid | 177 |
|
||||
* | SYS_mmap | 222 |
|
||||
* | SYS_munmap | 215 |
|
||||
* | SYS_mremap | 216 |
|
||||
* | SYS_time | 1062 |
|
||||
* | SYS_getmainvars | 2011 |
|
||||
* | SYS_rt_sigaction | 134 |
|
||||
* | SYS_writev | 66 |
|
||||
* | SYS_gettimeofday | 169 |
|
||||
* | SYS_times | 153 |
|
||||
* | SYS_fcntl | 25 |
|
||||
* | SYS_getdents | 61 |
|
||||
* | SYS_dup | 23 |
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef UNUSED
|
||||
#define UNUSED(x) (void)(x)
|
||||
#endif
|
||||
|
||||
static const char *TAG = "SYSCALL";
|
||||
|
||||
extern char _heap_start[];
|
||||
extern char _heap_end[];
|
||||
char *_heap_cur = &_heap_start[0];
|
||||
|
||||
|
||||
void __attribute__((noreturn)) sys_exit(int code)
|
||||
{
|
||||
/* Read core id */
|
||||
unsigned long core_id = current_coreid();
|
||||
/* First print some diagnostic information. */
|
||||
LOGW(TAG, "sys_exit called by core %ld with 0x%lx\r\n", core_id, (uint64_t)code);
|
||||
while (1)
|
||||
continue;
|
||||
}
|
||||
|
||||
static int sys_nosys(long a0, long a1, long a2, long a3, long a4, long a5, unsigned long n)
|
||||
{
|
||||
UNUSED(a3);
|
||||
UNUSED(a4);
|
||||
UNUSED(a5);
|
||||
|
||||
LOGE(TAG, "Unsupported syscall %ld: a0=%lx, a1=%lx, a2=%lx!\r\n", n, a0, a1, a2);
|
||||
while (1)
|
||||
continue;
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
static int sys_success(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static size_t sys_brk(size_t pos)
|
||||
{
|
||||
uintptr_t res = 0;
|
||||
/**
|
||||
* brk() sets the end of the data segment to the value
|
||||
* specified by addr, when that value is reasonable, the system
|
||||
* has enough memory, and the process does not exceed its
|
||||
* maximum data size.
|
||||
*
|
||||
* sbrk() increments the program's data space by increment
|
||||
* bytes. Calling sbrk() with an increment of 0 can be used to
|
||||
* find the current location of the program break.
|
||||
*
|
||||
* uintptr_t brk(uintptr_t ptr);
|
||||
*
|
||||
* IN : regs[10] = ptr
|
||||
* OUT: regs[10] = ptr
|
||||
*/
|
||||
|
||||
/**
|
||||
* First call: Initialization brk pointer. newlib will pass
|
||||
* ptr = 0 when it is first called. In this case the address
|
||||
* _heap_start will be return.
|
||||
*
|
||||
* Call again: Adjust brk pointer. The ptr never equal with
|
||||
* 0. If ptr is below _heap_end, then allocate memory.
|
||||
* Otherwise throw out of memory error, return -1.
|
||||
*/
|
||||
|
||||
if (pos)
|
||||
{
|
||||
/* Call again */
|
||||
if ((uintptr_t)pos > (uintptr_t)&_heap_end[0])
|
||||
{
|
||||
/* Memory out, return -ENOMEM */
|
||||
LOGE(TAG, "Out of memory\r\n");
|
||||
res = -ENOMEM;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Adjust brk pointer. */
|
||||
_heap_cur = (char *)(uintptr_t)pos;
|
||||
/* Return current address. */
|
||||
res = (uintptr_t)_heap_cur;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* First call, return initial address */
|
||||
res = (uintptr_t)&_heap_start[0];
|
||||
}
|
||||
return (size_t)res;
|
||||
}
|
||||
|
||||
static ssize_t sys_write(int file, const void *ptr, size_t len)
|
||||
{
|
||||
ssize_t res = -EBADF;
|
||||
|
||||
/**
|
||||
* Write to a file.
|
||||
*
|
||||
* ssize_t write(int file, const void *ptr, size_t len)
|
||||
*
|
||||
* IN : regs[10] = file, regs[11] = ptr, regs[12] = len
|
||||
* OUT: regs[10] = len
|
||||
*/
|
||||
|
||||
/* Get size to write */
|
||||
register size_t length = len;
|
||||
/* Get data pointer */
|
||||
register char *data = (char *)ptr;
|
||||
|
||||
if (STDOUT_FILENO == file || STDERR_FILENO == file)
|
||||
{
|
||||
/* Write data */
|
||||
while (length-- > 0 && *data != 0)
|
||||
uarths_putchar(*(data++));
|
||||
|
||||
/* Return the actual size written */
|
||||
res = len;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Not support yet */
|
||||
res = -ENOSYS;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static int sys_fstat(int file, struct stat *st)
|
||||
{
|
||||
int res = -EBADF;
|
||||
|
||||
/**
|
||||
* Status of an open file. The sys/stat.h header file required
|
||||
* is
|
||||
* distributed in the include subdirectory for this C library.
|
||||
*
|
||||
* int fstat(int file, struct stat* st)
|
||||
*
|
||||
* IN : regs[10] = file, regs[11] = st
|
||||
* OUT: regs[10] = Upon successful completion, 0 shall be
|
||||
* returned.
|
||||
* Otherwise, -1 shall be returned and errno set to indicate
|
||||
* the error.
|
||||
*/
|
||||
|
||||
UNUSED(file);
|
||||
|
||||
if (st != NULL)
|
||||
memset(st, 0, sizeof(struct stat));
|
||||
/* Return the result */
|
||||
res = -ENOSYS;
|
||||
/**
|
||||
* Note: This value will return to syscall wrapper, syscall
|
||||
* wrapper will set errno to ENOSYS and return -1
|
||||
*/
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static int sys_close(int file)
|
||||
{
|
||||
int res = -EBADF;
|
||||
|
||||
/**
|
||||
* Close a file.
|
||||
*
|
||||
* int close(int file)
|
||||
*
|
||||
* IN : regs[10] = file
|
||||
* OUT: regs[10] = Upon successful completion, 0 shall be
|
||||
* returned.
|
||||
* Otherwise, -1 shall be returned and errno set to indicate
|
||||
* the error.
|
||||
*/
|
||||
|
||||
UNUSED(file);
|
||||
/* Return the result */
|
||||
res = 0;
|
||||
return res;
|
||||
}
|
||||
|
||||
static int sys_gettimeofday(struct timeval *tp, void *tzp)
|
||||
{
|
||||
/**
|
||||
* Get the current time. Only relatively correct.
|
||||
*
|
||||
* int gettimeofday(struct timeval *tp, void *tzp)
|
||||
*
|
||||
* IN : regs[10] = tp
|
||||
* OUT: regs[10] = Upon successful completion, 0 shall be
|
||||
* returned.
|
||||
* Otherwise, -1 shall be returned and errno set to indicate
|
||||
* the error.
|
||||
*/
|
||||
UNUSED(tzp);
|
||||
|
||||
if (tp != NULL)
|
||||
{
|
||||
uint64_t clint_usec = clint->mtime / (sysctl_clock_get_freq(SYSCTL_CLOCK_CPU) / CLINT_CLOCK_DIV / 1000000UL);
|
||||
|
||||
tp->tv_sec = clint_usec / 1000000UL;
|
||||
tp->tv_usec = clint_usec % 1000000UL;
|
||||
}
|
||||
/* Return the result */
|
||||
return 0;
|
||||
}
|
||||
|
||||
uintptr_t __attribute__((weak))
|
||||
handle_ecall(uintptr_t cause, uintptr_t epc, uintptr_t regs[32], uintptr_t fregs[32])
|
||||
{
|
||||
UNUSED(cause);
|
||||
UNUSED(fregs);
|
||||
enum syscall_id_e
|
||||
{
|
||||
SYS_ID_NOSYS,
|
||||
SYS_ID_SUCCESS,
|
||||
SYS_ID_EXIT,
|
||||
SYS_ID_BRK,
|
||||
SYS_ID_WRITE,
|
||||
SYS_ID_FSTAT,
|
||||
SYS_ID_CLOSE,
|
||||
SYS_ID_GETTIMEOFDAY,
|
||||
SYS_ID_MAX
|
||||
};
|
||||
|
||||
static uintptr_t (* const syscall_table[])(long a0, long a1, long a2, long a3, long a4, long a5, unsigned long n) =
|
||||
{
|
||||
[SYS_ID_NOSYS] = (void *)sys_nosys,
|
||||
[SYS_ID_SUCCESS] = (void *)sys_success,
|
||||
[SYS_ID_EXIT] = (void *)sys_exit,
|
||||
[SYS_ID_BRK] = (void *)sys_brk,
|
||||
[SYS_ID_WRITE] = (void *)sys_write,
|
||||
[SYS_ID_FSTAT] = (void *)sys_fstat,
|
||||
[SYS_ID_CLOSE] = (void *)sys_close,
|
||||
[SYS_ID_GETTIMEOFDAY] = (void *)sys_gettimeofday,
|
||||
};
|
||||
|
||||
#if defined(__GNUC__)
|
||||
#pragma GCC diagnostic ignored "-Woverride-init"
|
||||
#endif
|
||||
static const uint8_t syscall_id_table[0x100] =
|
||||
{
|
||||
[0x00 ... 0xFF] = SYS_ID_NOSYS,
|
||||
[0xFF & SYS_exit] = SYS_ID_EXIT,
|
||||
[0xFF & SYS_exit_group] = SYS_ID_EXIT,
|
||||
[0xFF & SYS_getpid] = SYS_ID_NOSYS,
|
||||
[0xFF & SYS_kill] = SYS_ID_NOSYS,
|
||||
[0xFF & SYS_read] = SYS_ID_NOSYS,
|
||||
[0xFF & SYS_write] = SYS_ID_WRITE,
|
||||
[0xFF & SYS_open] = SYS_ID_NOSYS,
|
||||
[0xFF & SYS_openat] = SYS_ID_NOSYS,
|
||||
[0xFF & SYS_close] = SYS_ID_CLOSE,
|
||||
[0xFF & SYS_lseek] = SYS_ID_NOSYS,
|
||||
[0xFF & SYS_brk] = SYS_ID_BRK,
|
||||
[0xFF & SYS_link] = SYS_ID_NOSYS,
|
||||
[0xFF & SYS_unlink] = SYS_ID_NOSYS,
|
||||
[0xFF & SYS_mkdir] = SYS_ID_NOSYS,
|
||||
[0xFF & SYS_chdir] = SYS_ID_NOSYS,
|
||||
[0xFF & SYS_getcwd] = SYS_ID_NOSYS,
|
||||
[0xFF & SYS_stat] = SYS_ID_NOSYS,
|
||||
[0xFF & SYS_fstat] = SYS_ID_FSTAT,
|
||||
[0xFF & SYS_lstat] = SYS_ID_NOSYS,
|
||||
[0xFF & SYS_fstatat] = SYS_ID_NOSYS,
|
||||
[0xFF & SYS_access] = SYS_ID_NOSYS,
|
||||
[0xFF & SYS_faccessat] = SYS_ID_NOSYS,
|
||||
[0xFF & SYS_pread] = SYS_ID_NOSYS,
|
||||
[0xFF & SYS_pwrite] = SYS_ID_NOSYS,
|
||||
[0xFF & SYS_uname] = SYS_ID_NOSYS,
|
||||
[0xFF & SYS_getuid] = SYS_ID_NOSYS,
|
||||
[0xFF & SYS_geteuid] = SYS_ID_NOSYS,
|
||||
[0xFF & SYS_getgid] = SYS_ID_NOSYS,
|
||||
[0xFF & SYS_getegid] = SYS_ID_NOSYS,
|
||||
[0xFF & SYS_mmap] = SYS_ID_NOSYS,
|
||||
[0xFF & SYS_munmap] = SYS_ID_NOSYS,
|
||||
[0xFF & SYS_mremap] = SYS_ID_NOSYS,
|
||||
[0xFF & SYS_time] = SYS_ID_NOSYS,
|
||||
[0xFF & SYS_getmainvars] = SYS_ID_NOSYS,
|
||||
[0xFF & SYS_rt_sigaction] = SYS_ID_NOSYS,
|
||||
[0xFF & SYS_writev] = SYS_ID_NOSYS,
|
||||
[0xFF & SYS_gettimeofday] = SYS_ID_GETTIMEOFDAY,
|
||||
[0xFF & SYS_times] = SYS_ID_NOSYS,
|
||||
[0xFF & SYS_fcntl] = SYS_ID_NOSYS,
|
||||
[0xFF & SYS_getdents] = SYS_ID_NOSYS,
|
||||
[0xFF & SYS_dup] = SYS_ID_NOSYS,
|
||||
};
|
||||
#if defined(__GNUC__)
|
||||
#pragma GCC diagnostic warning "-Woverride-init"
|
||||
#endif
|
||||
|
||||
regs[10] = syscall_table[syscall_id_table[0xFF & regs[17]]]
|
||||
(
|
||||
regs[10], /* a0 */
|
||||
regs[11], /* a1 */
|
||||
regs[12], /* a2 */
|
||||
regs[13], /* a3 */
|
||||
regs[14], /* a4 */
|
||||
regs[15], /* a5 */
|
||||
regs[17] /* n */
|
||||
);
|
||||
|
||||
return epc + 4;
|
||||
}
|
||||
|
||||
uintptr_t __attribute__((weak, alias("handle_ecall")))
|
||||
handle_ecall_u(uintptr_t cause, uintptr_t epc, uintptr_t regs[32], uintptr_t fregs[32]);
|
||||
|
||||
uintptr_t __attribute__((weak, alias("handle_ecall")))
|
||||
handle_ecall_h(uintptr_t cause, uintptr_t epc, uintptr_t regs[32], uintptr_t fregs[32]);
|
||||
|
||||
uintptr_t __attribute__((weak, alias("handle_ecall")))
|
||||
handle_ecall_s(uintptr_t cause, uintptr_t epc, uintptr_t regs[32], uintptr_t fregs[32]);
|
||||
|
||||
uintptr_t __attribute__((weak, alias("handle_ecall")))
|
||||
handle_ecall_m(uintptr_t cause, uintptr_t epc, uintptr_t regs[32], uintptr_t fregs[32]);
|
||||
|
||||
uintptr_t __attribute__((weak))
|
||||
handle_misaligned_fetch(uintptr_t cause, uintptr_t epc, uintptr_t regs[32], uintptr_t fregs[32])
|
||||
{
|
||||
dump_core("misaligned fetch", cause, epc, regs, fregs);
|
||||
sys_exit(1337);
|
||||
return epc;
|
||||
}
|
||||
|
||||
uintptr_t __attribute__((weak))
|
||||
handle_fault_fetch(uintptr_t cause, uintptr_t epc, uintptr_t regs[32], uintptr_t fregs[32])
|
||||
{
|
||||
dump_core("fault fetch", cause, epc, regs, fregs);
|
||||
sys_exit(1337);
|
||||
return epc;
|
||||
}
|
||||
|
||||
uintptr_t __attribute__((weak))
|
||||
handle_illegal_instruction(uintptr_t cause, uintptr_t epc, uintptr_t regs[32], uintptr_t fregs[32])
|
||||
{
|
||||
dump_core("illegal instruction", cause, epc, regs, fregs);
|
||||
sys_exit(1337);
|
||||
return epc;
|
||||
}
|
||||
|
||||
uintptr_t __attribute__((weak))
|
||||
handle_breakpoint(uintptr_t cause, uintptr_t epc, uintptr_t regs[32], uintptr_t fregs[32])
|
||||
{
|
||||
dump_core("breakpoint", cause, epc, regs, fregs);
|
||||
sys_exit(1337);
|
||||
return epc;
|
||||
}
|
||||
|
||||
uintptr_t __attribute__((weak))
|
||||
handle_misaligned_load(uintptr_t cause, uintptr_t epc, uintptr_t regs[32], uintptr_t fregs[32])
|
||||
{
|
||||
/* notice this function only support 16bit or 32bit instruction */
|
||||
|
||||
bool compressed = (*(unsigned short *)epc & 3) != 3;
|
||||
bool fpu = 0; /* load to fpu ? */
|
||||
uintptr_t addr = 0; /* src addr */
|
||||
uint8_t src = 0; /* src register */
|
||||
uint8_t dst = 0; /* dst register */
|
||||
uint8_t len = 0; /* data length */
|
||||
int offset = 0; /* addr offset to addr in reg */
|
||||
bool unsigned_ = 0; /* unsigned */
|
||||
uint64_t data_load = 0;/* real data load */
|
||||
|
||||
if (compressed)
|
||||
{
|
||||
/* compressed instruction should not get this fault. */
|
||||
goto on_error;
|
||||
}
|
||||
else
|
||||
{
|
||||
uint32_t instruct = *(uint32_t *)epc;
|
||||
uint8_t opcode = instruct&0x7F;
|
||||
|
||||
dst = (instruct >> 7)&0x1F;
|
||||
len = (instruct >> 12)&3;
|
||||
unsigned_ = (instruct >> 14)&1;
|
||||
src = (instruct >> 15)&0x1F;
|
||||
offset = (instruct >> 20);
|
||||
len = 1 << len;
|
||||
switch (opcode)
|
||||
{
|
||||
case 3:/* load */
|
||||
break;
|
||||
case 7:/* fpu load */
|
||||
fpu = 1;
|
||||
break;
|
||||
default:
|
||||
goto on_error;
|
||||
}
|
||||
}
|
||||
|
||||
if (offset >> 11)
|
||||
offset = -((offset & 0x3FF) + 1);
|
||||
|
||||
addr = (uint64_t)((uint64_t)regs[src] + offset);
|
||||
|
||||
for (int i = 0; i < len; ++i)
|
||||
data_load |= ((uint64_t)*((uint8_t *)addr + i)) << (8 * i);
|
||||
|
||||
|
||||
if (!unsigned_ & !fpu)
|
||||
{
|
||||
/* adjust sign */
|
||||
switch (len)
|
||||
{
|
||||
case 1:
|
||||
data_load = (uint64_t)(int64_t)((int8_t)data_load);
|
||||
break;
|
||||
case 2:
|
||||
data_load = (uint64_t)(int64_t)((int16_t)data_load);
|
||||
break;
|
||||
case 4:
|
||||
data_load = (uint64_t)(int64_t)((int32_t)data_load);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (fpu)
|
||||
fregs[dst] = data_load;
|
||||
else
|
||||
regs[dst] = data_load;
|
||||
|
||||
LOGV(TAG, "misaligned load recovered at %08lx. len:%02d,addr:%08lx,reg:%02d,data:%016lx,signed:%1d,float:%1d", (uint64_t)epc, len, (uint64_t)addr, dst, data_load, !unsigned_, fpu);
|
||||
|
||||
return epc + (compressed ? 2 : 4);
|
||||
on_error:
|
||||
dump_core("misaligned load", cause, epc, regs, fregs);
|
||||
sys_exit(1337);
|
||||
return epc;
|
||||
}
|
||||
|
||||
uintptr_t __attribute__((weak))
|
||||
handle_fault_load(uintptr_t cause, uintptr_t epc, uintptr_t regs[32], uintptr_t fregs[32])
|
||||
{
|
||||
dump_core("fault load", cause, epc, regs, fregs);
|
||||
sys_exit(1337);
|
||||
return epc;
|
||||
}
|
||||
|
||||
uintptr_t __attribute__((weak))
|
||||
handle_misaligned_store(uintptr_t cause, uintptr_t epc, uintptr_t regs[32], uintptr_t fregs[32])
|
||||
{
|
||||
/* notice this function only support 16bit or 32bit instruction */
|
||||
|
||||
bool compressed = (*(unsigned short *)epc & 3) != 3;
|
||||
bool fpu = 0; /* store to fpu*/
|
||||
uintptr_t addr = 0; /* src addr*/
|
||||
uint8_t src = 0; /* src register*/
|
||||
uint8_t dst = 0; /* dst register*/
|
||||
uint8_t len = 0; /* data length*/
|
||||
int offset = 0; /* addr offset to addr in reg*/
|
||||
uint64_t data_store = 0;/* real data store*/
|
||||
|
||||
if (compressed)
|
||||
{
|
||||
/* compressed instruction should not get this fault. */
|
||||
goto on_error;
|
||||
}
|
||||
else
|
||||
{
|
||||
uint32_t instruct = *(uint32_t *)epc;
|
||||
uint8_t opcode = instruct&0x7F;
|
||||
|
||||
len = (instruct >> 12)&7;
|
||||
dst = (instruct >> 15)&0x1F;
|
||||
src = (instruct >> 20)&0x1F;
|
||||
offset = ((instruct >> 7)&0x1F) | ((instruct >> 20)&0xFE0);
|
||||
len = 1 << len;
|
||||
switch (opcode)
|
||||
{
|
||||
case 0x23:/* store */
|
||||
break;
|
||||
case 0x27:/* fpu store */
|
||||
fpu = 1;
|
||||
break;
|
||||
default:
|
||||
goto on_error;
|
||||
}
|
||||
}
|
||||
|
||||
if (offset >> 11)
|
||||
offset = -((offset & 0x3FF) + 1);
|
||||
|
||||
addr = (uint64_t)((uint64_t)regs[dst] + offset);
|
||||
|
||||
|
||||
if (fpu)
|
||||
data_store = fregs[src];
|
||||
else
|
||||
data_store = regs[src];
|
||||
|
||||
for (int i = 0; i < len; ++i)
|
||||
*((uint8_t *)addr + i) = (data_store >> (i*8)) & 0xFF;
|
||||
|
||||
LOGV(TAG, "misaligned store recovered at %08lx. len:%02d,addr:%08lx,reg:%02d,data:%016lx,float:%1d", (uint64_t)epc, len, (uint64_t)addr, src, data_store, fpu);
|
||||
|
||||
return epc + (compressed ? 2 : 4);
|
||||
on_error:
|
||||
dump_core("misaligned store", cause, epc, regs, fregs);
|
||||
sys_exit(1337);
|
||||
return epc;
|
||||
}
|
||||
|
||||
uintptr_t __attribute__((weak))
|
||||
handle_fault_store(uintptr_t cause, uintptr_t epc, uintptr_t regs[32], uintptr_t fregs[32])
|
||||
{
|
||||
dump_core("fault store", cause, epc, regs, fregs);
|
||||
sys_exit(1337);
|
||||
return epc;
|
||||
}
|
||||
|
||||
uintptr_t handle_syscall(uintptr_t cause, uintptr_t epc, uintptr_t regs[32], uintptr_t fregs[32])
|
||||
{
|
||||
|
||||
static uintptr_t (* const cause_table[])(uintptr_t cause, uintptr_t epc, uintptr_t regs[32], uintptr_t fregs[32]) =
|
||||
{
|
||||
[CAUSE_MISALIGNED_FETCH] = handle_misaligned_fetch,
|
||||
[CAUSE_FAULT_FETCH] = handle_fault_fetch,
|
||||
[CAUSE_ILLEGAL_INSTRUCTION] = handle_illegal_instruction,
|
||||
[CAUSE_BREAKPOINT] = handle_breakpoint,
|
||||
[CAUSE_MISALIGNED_LOAD] = handle_misaligned_load,
|
||||
[CAUSE_FAULT_LOAD] = handle_fault_load,
|
||||
[CAUSE_MISALIGNED_STORE] = handle_misaligned_store,
|
||||
[CAUSE_FAULT_STORE] = handle_fault_store,
|
||||
[CAUSE_USER_ECALL] = handle_ecall_u,
|
||||
[CAUSE_SUPERVISOR_ECALL] = handle_ecall_h,
|
||||
[CAUSE_HYPERVISOR_ECALL] = handle_ecall_s,
|
||||
[CAUSE_MACHINE_ECALL] = handle_ecall_m,
|
||||
};
|
||||
|
||||
return cause_table[cause](cause, epc, regs, fregs);
|
||||
}
|
||||
|
||||
size_t get_free_heap_size(void)
|
||||
{
|
||||
return (size_t)(&_heap_end[0] - _heap_cur);
|
||||
}
|
||||
|
||||
@@ -1,803 +0,0 @@
|
||||
/* Copyright 2018 Canaan Inc.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* http://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.
|
||||
*/
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "sysctl.h"
|
||||
#include "aes.h"
|
||||
#include "utils.h"
|
||||
|
||||
volatile aes_t *const aes = (volatile aes_t *)AES_BASE_ADDR;
|
||||
|
||||
static void aes_clk_init()
|
||||
{
|
||||
sysctl_clock_enable(SYSCTL_CLOCK_AES);
|
||||
sysctl_reset(SYSCTL_RESET_AES);
|
||||
}
|
||||
|
||||
static void aes_write_aad(uint32_t aad_data)
|
||||
{
|
||||
aes->aes_aad_data = aad_data;
|
||||
}
|
||||
|
||||
static void aes_write_text(uint32_t text_data)
|
||||
{
|
||||
aes->aes_text_data = text_data;
|
||||
}
|
||||
|
||||
static void gcm_write_tag(uint32_t *tag)
|
||||
{
|
||||
aes->gcm_in_tag[0] = tag[3];
|
||||
aes->gcm_in_tag[1] = tag[2];
|
||||
aes->gcm_in_tag[2] = tag[1];
|
||||
aes->gcm_in_tag[3] = tag[0];
|
||||
}
|
||||
|
||||
static uint32_t aes_get_data_in_flag(void)
|
||||
{
|
||||
return aes->data_in_flag;
|
||||
}
|
||||
|
||||
static uint32_t aes_get_data_out_flag(void)
|
||||
{
|
||||
return aes->data_out_flag;
|
||||
}
|
||||
|
||||
static uint32_t gcm_get_tag_in_flag(void)
|
||||
{
|
||||
return aes->tag_in_flag;
|
||||
}
|
||||
|
||||
static uint32_t aes_read_out_data(void)
|
||||
{
|
||||
return aes->aes_out_data;
|
||||
}
|
||||
|
||||
static uint32_t gcm_get_tag_chk(void)
|
||||
{
|
||||
return aes->tag_chk;
|
||||
}
|
||||
|
||||
static void gcm_clear_chk_tag(void)
|
||||
{
|
||||
aes->tag_clear = 0;
|
||||
}
|
||||
|
||||
static uint32_t gcm_check_tag(uint32_t *gcm_tag)
|
||||
{
|
||||
while (!gcm_get_tag_in_flag())
|
||||
;
|
||||
gcm_write_tag(gcm_tag);
|
||||
while (!gcm_get_tag_chk())
|
||||
;
|
||||
if (gcm_get_tag_chk() == 0x2)
|
||||
{
|
||||
gcm_clear_chk_tag();
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
gcm_clear_chk_tag();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void gcm_get_tag(uint8_t *gcm_tag)
|
||||
{
|
||||
uint32_t uint32_tag;
|
||||
uint8_t i = 0;
|
||||
|
||||
uint32_tag = aes->gcm_out_tag[3];
|
||||
gcm_tag[i++] = (uint8_t)((uint32_tag >> 24) & 0xff);
|
||||
gcm_tag[i++] = (uint8_t)((uint32_tag >> 16) & 0xff);
|
||||
gcm_tag[i++] = (uint8_t)((uint32_tag >> 8) & 0xff);
|
||||
gcm_tag[i++] = (uint8_t)((uint32_tag)&0xff);
|
||||
|
||||
uint32_tag = aes->gcm_out_tag[2];
|
||||
gcm_tag[i++] = (uint8_t)((uint32_tag >> 24) & 0xff);
|
||||
gcm_tag[i++] = (uint8_t)((uint32_tag >> 16) & 0xff);
|
||||
gcm_tag[i++] = (uint8_t)((uint32_tag >> 8) & 0xff);
|
||||
gcm_tag[i++] = (uint8_t)((uint32_tag)&0xff);
|
||||
|
||||
uint32_tag = aes->gcm_out_tag[1];
|
||||
gcm_tag[i++] = (uint8_t)((uint32_tag >> 24) & 0xff);
|
||||
gcm_tag[i++] = (uint8_t)((uint32_tag >> 16) & 0xff);
|
||||
gcm_tag[i++] = (uint8_t)((uint32_tag >> 8) & 0xff);
|
||||
gcm_tag[i++] = (uint8_t)((uint32_tag)&0xff);
|
||||
|
||||
uint32_tag = aes->gcm_out_tag[0];
|
||||
gcm_tag[i++] = (uint8_t)((uint32_tag >> 24) & 0xff);
|
||||
gcm_tag[i++] = (uint8_t)((uint32_tag >> 16) & 0xff);
|
||||
gcm_tag[i++] = (uint8_t)((uint32_tag >> 8) & 0xff);
|
||||
gcm_tag[i++] = (uint8_t)((uint32_tag)&0xff);
|
||||
|
||||
gcm_check_tag((uint32_t *)gcm_tag);
|
||||
}
|
||||
|
||||
|
||||
void aes_init(uint8_t *input_key, size_t input_key_len, uint8_t *iv,size_t iv_len, uint8_t *gcm_aad,
|
||||
aes_cipher_mode_t cipher_mode, aes_encrypt_sel_t encrypt_sel, size_t gcm_aad_len, size_t input_data_len)
|
||||
{
|
||||
size_t remainder, uint32_num, uint8_num, i;
|
||||
uint32_t uint32_data;
|
||||
uint8_t uint8_data[4] = {0};
|
||||
size_t padding_len = input_data_len;
|
||||
aes_clk_init();
|
||||
if ((cipher_mode == AES_ECB) || (cipher_mode == AES_CBC))
|
||||
padding_len = ((input_data_len + 15) / 16) * 16;
|
||||
aes->aes_endian |= 1;
|
||||
uint32_num = input_key_len / 4;
|
||||
for (i = 0; i < uint32_num; i++)
|
||||
{
|
||||
if (i < 4)
|
||||
aes->aes_key[i] = *((uint32_t *)(&input_key[input_key_len - (4 * i) - 4]));
|
||||
else
|
||||
aes->aes_key_ext[i - 4] = *((uint32_t *)(&input_key[input_key_len - (4 * i) - 4]));
|
||||
}
|
||||
|
||||
uint32_num = iv_len / 4;
|
||||
for (i = 0; i < uint32_num; i++)
|
||||
aes->aes_iv[i] = *((uint32_t *)(&iv[iv_len - (4 * i) - 4]));
|
||||
|
||||
aes->mode_ctl.kmode = input_key_len / 8 - 2; /* b'00:AES_128 b'01:AES_192 b'10:AES_256 b'11:RESERVED */
|
||||
aes->mode_ctl.cipher_mode = cipher_mode;
|
||||
aes->encrypt_sel = encrypt_sel;
|
||||
aes->gb_aad_num = gcm_aad_len - 1;
|
||||
aes->gb_pc_num = padding_len - 1;
|
||||
aes->gb_aes_en |= 1;
|
||||
|
||||
if (cipher_mode == AES_GCM)
|
||||
{
|
||||
uint32_num = gcm_aad_len / 4;
|
||||
for (i = 0; i < uint32_num; i++)
|
||||
{
|
||||
uint32_data = *((uint32_t *)(&gcm_aad[i * 4]));
|
||||
while (!aes_get_data_in_flag())
|
||||
;
|
||||
aes_write_aad(uint32_data);
|
||||
}
|
||||
uint8_num = 4 * uint32_num;
|
||||
remainder = gcm_aad_len % 4;
|
||||
if (remainder)
|
||||
{
|
||||
switch (remainder)
|
||||
{
|
||||
case 1:
|
||||
uint8_data[0] = gcm_aad[uint8_num];
|
||||
break;
|
||||
case 2:
|
||||
uint8_data[0] = gcm_aad[uint8_num];
|
||||
uint8_data[1] = gcm_aad[uint8_num + 1];
|
||||
break;
|
||||
case 3:
|
||||
uint8_data[0] = gcm_aad[uint8_num];
|
||||
uint8_data[1] = gcm_aad[uint8_num + 1];
|
||||
uint8_data[2] = gcm_aad[uint8_num + 2];
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
uint32_data = *((uint32_t *)(&uint8_data[0]));
|
||||
while (!aes_get_data_in_flag())
|
||||
;
|
||||
aes_write_aad(uint32_data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void aes_input_bytes(const uint8_t *input_data, size_t input_data_len, aes_cipher_mode_t cipher_mode)
|
||||
{
|
||||
size_t padding_len, uint32_num, uint8_num, remainder, i;
|
||||
uint32_t uint32_data;
|
||||
uint8_t uint8_data[4] = {0};
|
||||
|
||||
padding_len = ((input_data_len + 15) / 16) * 16;
|
||||
uint32_num = input_data_len / 4;
|
||||
for (i = 0; i < uint32_num; i++)
|
||||
{
|
||||
uint32_data = *((uint32_t *)(&input_data[i * 4]));
|
||||
while (!aes_get_data_in_flag())
|
||||
;
|
||||
aes_write_text(uint32_data);
|
||||
}
|
||||
uint8_num = 4 * uint32_num;
|
||||
remainder = input_data_len % 4;
|
||||
if (remainder)
|
||||
{
|
||||
switch (remainder)
|
||||
{
|
||||
case 1:
|
||||
uint8_data[0] = input_data[uint8_num];
|
||||
break;
|
||||
case 2:
|
||||
uint8_data[0] = input_data[uint8_num];
|
||||
uint8_data[1] = input_data[uint8_num + 1];
|
||||
break;
|
||||
case 3:
|
||||
uint8_data[0] = input_data[uint8_num];
|
||||
uint8_data[1] = input_data[uint8_num + 1];
|
||||
uint8_data[2] = input_data[uint8_num + 2];
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
uint32_data = *((uint32_t *)(&uint8_data[0]));
|
||||
while (!aes_get_data_in_flag())
|
||||
;
|
||||
aes_write_text(uint32_data);
|
||||
}
|
||||
if ((cipher_mode == AES_ECB) || (cipher_mode == AES_CBC))
|
||||
{
|
||||
uint32_num = (padding_len - input_data_len) / 4;
|
||||
for (i = 0; i < uint32_num; i++)
|
||||
{
|
||||
while (!aes_get_data_in_flag())
|
||||
;
|
||||
aes_write_text(0);
|
||||
}
|
||||
uint32_num = padding_len / 4;
|
||||
}
|
||||
}
|
||||
|
||||
static void process_less_80_bytes(uint8_t *input_data, uint8_t *output_data, size_t input_data_len, aes_cipher_mode_t cipher_mode)
|
||||
{
|
||||
size_t padding_len, uint32_num, uint8_num, remainder, i;
|
||||
uint32_t uint32_data;
|
||||
uint8_t uint8_data[4] = {0};
|
||||
|
||||
padding_len = ((input_data_len + 15) / 16) * 16;
|
||||
uint32_num = input_data_len / 4;
|
||||
for (i = 0; i < uint32_num; i++)
|
||||
{
|
||||
uint32_data = *((uint32_t *)(&input_data[i * 4]));
|
||||
while (!aes_get_data_in_flag())
|
||||
;
|
||||
aes_write_text(uint32_data);
|
||||
}
|
||||
uint8_num = 4 * uint32_num;
|
||||
remainder = input_data_len % 4;
|
||||
if (remainder)
|
||||
{
|
||||
switch (remainder)
|
||||
{
|
||||
case 1:
|
||||
uint8_data[0] = input_data[uint8_num];
|
||||
break;
|
||||
case 2:
|
||||
uint8_data[0] = input_data[uint8_num];
|
||||
uint8_data[1] = input_data[uint8_num + 1];
|
||||
break;
|
||||
case 3:
|
||||
uint8_data[0] = input_data[uint8_num];
|
||||
uint8_data[1] = input_data[uint8_num + 1];
|
||||
uint8_data[2] = input_data[uint8_num + 2];
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
uint32_data = *((uint32_t *)(&uint8_data[0]));
|
||||
while (!aes_get_data_in_flag())
|
||||
;
|
||||
aes_write_text(uint32_data);
|
||||
}
|
||||
if ((cipher_mode == AES_ECB) || (cipher_mode == AES_CBC))
|
||||
{
|
||||
uint32_num = (padding_len - input_data_len) / 4;
|
||||
for (i = 0; i < uint32_num; i++)
|
||||
{
|
||||
while (!aes_get_data_in_flag())
|
||||
;
|
||||
aes_write_text(0);
|
||||
}
|
||||
uint32_num = padding_len / 4;
|
||||
}
|
||||
for (i = 0; i < uint32_num; i++)
|
||||
{
|
||||
while (!aes_get_data_out_flag())
|
||||
;
|
||||
*((uint32_t *)(&output_data[i * 4])) = aes_read_out_data();
|
||||
}
|
||||
if ((cipher_mode == AES_GCM) && (remainder))
|
||||
{
|
||||
while (!aes_get_data_out_flag())
|
||||
;
|
||||
*((uint32_t *)(&uint8_data[0])) = aes_read_out_data();
|
||||
switch (remainder)
|
||||
{
|
||||
case 1:
|
||||
output_data[uint32_num * 4] = uint8_data[0];
|
||||
break;
|
||||
case 2:
|
||||
output_data[uint32_num * 4] = uint8_data[0];
|
||||
output_data[(i * 4) + 1] = uint8_data[1];
|
||||
break;
|
||||
case 3:
|
||||
output_data[uint32_num * 4] = uint8_data[0];
|
||||
output_data[(i * 4) + 1] = uint8_data[1];
|
||||
output_data[(i * 4) + 2] = uint8_data[2];
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void aes_process(uint8_t *input_data, uint8_t *output_data, size_t input_data_len, aes_cipher_mode_t cipher_mode)
|
||||
{
|
||||
size_t temp_len = 0;
|
||||
uint32_t i = 0;
|
||||
|
||||
if (input_data_len >= 80)
|
||||
{
|
||||
for (i = 0; i < (input_data_len / 80); i++)
|
||||
process_less_80_bytes(&input_data[i * 80], &output_data[i * 80], 80, cipher_mode);
|
||||
}
|
||||
temp_len = input_data_len % 80;
|
||||
if (temp_len)
|
||||
process_less_80_bytes(&input_data[i * 80], &output_data[i * 80], temp_len, cipher_mode);
|
||||
}
|
||||
|
||||
void aes_ecb128_hard_decrypt(uint8_t *input_key, uint8_t *input_data, size_t input_len, uint8_t *output_data)
|
||||
{
|
||||
size_t padding_len = ((input_len + 15) / 16) * 16;
|
||||
aes_init(input_key, AES_128, NULL, 0L, NULL, AES_ECB, AES_HARD_DECRYPTION, 0L, input_len);
|
||||
aes_process(input_data, output_data, padding_len, AES_ECB);
|
||||
}
|
||||
|
||||
void aes_ecb128_hard_encrypt(uint8_t *input_key, uint8_t *input_data, size_t input_len, uint8_t *output_data)
|
||||
{
|
||||
aes_init(input_key, AES_128, NULL, 0L, NULL, AES_ECB, AES_HARD_ENCRYPTION, 0L, input_len);
|
||||
aes_process(input_data, output_data, input_len, AES_ECB);
|
||||
}
|
||||
|
||||
void aes_ecb192_hard_decrypt(uint8_t *input_key, uint8_t *input_data, size_t input_len, uint8_t *output_data)
|
||||
{
|
||||
size_t padding_len = ((input_len + 15) / 16) * 16;
|
||||
aes_init(input_key, AES_192, NULL, 0L, NULL, AES_ECB, AES_HARD_DECRYPTION, 0L, input_len);
|
||||
aes_process(input_data, output_data, padding_len, AES_ECB);
|
||||
}
|
||||
|
||||
void aes_ecb192_hard_encrypt(uint8_t *input_key, uint8_t *input_data, size_t input_len, uint8_t *output_data)
|
||||
{
|
||||
aes_init(input_key, AES_192, NULL, 0L, NULL, AES_ECB, AES_HARD_ENCRYPTION, 0L, input_len);
|
||||
aes_process(input_data, output_data, input_len, AES_ECB);
|
||||
}
|
||||
|
||||
void aes_ecb256_hard_decrypt(uint8_t *input_key, uint8_t *input_data, size_t input_len, uint8_t *output_data)
|
||||
{
|
||||
size_t padding_len = ((input_len + 15) / 16) * 16;
|
||||
aes_init(input_key, AES_256, NULL, 0L, NULL, AES_ECB, AES_HARD_DECRYPTION, 0L, input_len);
|
||||
aes_process(input_data, output_data, padding_len, AES_ECB);
|
||||
}
|
||||
|
||||
void aes_ecb256_hard_encrypt(uint8_t *input_key, uint8_t *input_data, size_t input_len, uint8_t *output_data)
|
||||
{
|
||||
aes_init(input_key, AES_256, NULL, 0L, NULL, AES_ECB, AES_HARD_ENCRYPTION, 0L, input_len);
|
||||
aes_process(input_data, output_data, input_len, AES_ECB);
|
||||
}
|
||||
|
||||
void aes_cbc128_hard_decrypt(cbc_context_t *context, uint8_t *input_data, size_t input_len, uint8_t *output_data)
|
||||
{
|
||||
size_t padding_len = ((input_len + 15) / 16) * 16;
|
||||
aes_init(context->input_key, AES_128, context->iv, IV_LEN_128, NULL, AES_CBC, AES_HARD_DECRYPTION, 0L, input_len);
|
||||
aes_process(input_data, output_data, padding_len, AES_CBC);
|
||||
}
|
||||
|
||||
void aes_cbc128_hard_encrypt(cbc_context_t *context, uint8_t *input_data, size_t input_len, uint8_t *output_data)
|
||||
{
|
||||
aes_init(context->input_key, AES_128, context->iv, IV_LEN_128, NULL, AES_CBC, AES_HARD_ENCRYPTION, 0L, input_len);
|
||||
aes_process(input_data, output_data, input_len, AES_CBC);
|
||||
}
|
||||
|
||||
void aes_cbc192_hard_decrypt(cbc_context_t *context, uint8_t *input_data, size_t input_len, uint8_t *output_data)
|
||||
{
|
||||
size_t padding_len = ((input_len + 15) / 16) * 16;
|
||||
aes_init(context->input_key, AES_192, context->iv, IV_LEN_128, NULL, AES_CBC, AES_HARD_DECRYPTION, 0L, input_len);
|
||||
aes_process(input_data, output_data, padding_len, AES_CBC);
|
||||
}
|
||||
|
||||
void aes_cbc192_hard_encrypt(cbc_context_t *context, uint8_t *input_data, size_t input_len, uint8_t *output_data)
|
||||
{
|
||||
aes_init(context->input_key, AES_192, context->iv, IV_LEN_128, NULL, AES_CBC, AES_HARD_ENCRYPTION, 0L, input_len);
|
||||
aes_process(input_data, output_data, input_len, AES_CBC);
|
||||
}
|
||||
|
||||
void aes_cbc256_hard_decrypt(cbc_context_t *context, uint8_t *input_data, size_t input_len, uint8_t *output_data)
|
||||
{
|
||||
size_t padding_len = ((input_len + 15) / 16) * 16;
|
||||
aes_init(context->input_key, AES_256, context->iv, IV_LEN_128, NULL, AES_CBC, AES_HARD_DECRYPTION, 0L, input_len);
|
||||
aes_process(input_data, output_data, padding_len, AES_CBC);
|
||||
}
|
||||
|
||||
void aes_cbc256_hard_encrypt(cbc_context_t *context, uint8_t *input_data, size_t input_len, uint8_t *output_data)
|
||||
{
|
||||
aes_init(context->input_key, AES_256, context->iv, IV_LEN_128, NULL, AES_CBC, AES_HARD_ENCRYPTION, 0L, input_len);
|
||||
aes_process(input_data, output_data, input_len, AES_CBC);
|
||||
}
|
||||
|
||||
void aes_gcm128_hard_decrypt(gcm_context_t *context, uint8_t *input_data, size_t input_len, uint8_t *output_data, uint8_t *gcm_tag)
|
||||
{
|
||||
aes_init(context->input_key, AES_128, context->iv, IV_LEN_96, context->gcm_aad,
|
||||
AES_GCM, AES_HARD_DECRYPTION, context->gcm_aad_len, input_len);
|
||||
aes_process(input_data, output_data, input_len, AES_GCM);
|
||||
gcm_get_tag(gcm_tag);
|
||||
}
|
||||
|
||||
void aes_gcm128_hard_encrypt(gcm_context_t *context, uint8_t *input_data, size_t input_len, uint8_t *output_data, uint8_t *gcm_tag)
|
||||
{
|
||||
aes_init(context->input_key, AES_128, context->iv, IV_LEN_96, context->gcm_aad,
|
||||
AES_GCM, AES_HARD_ENCRYPTION, context->gcm_aad_len, input_len);
|
||||
aes_process(input_data, output_data, input_len, AES_GCM);
|
||||
gcm_get_tag(gcm_tag);
|
||||
}
|
||||
|
||||
void aes_gcm192_hard_decrypt(gcm_context_t *context, uint8_t *input_data, size_t input_len, uint8_t *output_data, uint8_t *gcm_tag)
|
||||
{
|
||||
aes_init(context->input_key, AES_192, context->iv, IV_LEN_96, context->gcm_aad,
|
||||
AES_GCM, AES_HARD_DECRYPTION, context->gcm_aad_len, input_len);
|
||||
aes_process(input_data, output_data, input_len, AES_GCM);
|
||||
gcm_get_tag(gcm_tag);
|
||||
}
|
||||
|
||||
void aes_gcm192_hard_encrypt(gcm_context_t *context, uint8_t *input_data, size_t input_len, uint8_t *output_data, uint8_t *gcm_tag)
|
||||
{
|
||||
aes_init(context->input_key, AES_192, context->iv, IV_LEN_96, context->gcm_aad,
|
||||
AES_GCM, AES_HARD_ENCRYPTION, context->gcm_aad_len, input_len);
|
||||
aes_process(input_data, output_data, input_len, AES_GCM);
|
||||
gcm_get_tag(gcm_tag);
|
||||
}
|
||||
|
||||
void aes_gcm256_hard_decrypt(gcm_context_t *context, uint8_t *input_data, size_t input_len, uint8_t *output_data, uint8_t *gcm_tag)
|
||||
{
|
||||
aes_init(context->input_key, AES_256, context->iv, IV_LEN_96, context->gcm_aad,
|
||||
AES_GCM, AES_HARD_DECRYPTION, context->gcm_aad_len, input_len);
|
||||
aes_process(input_data, output_data, input_len, AES_GCM);
|
||||
gcm_get_tag(gcm_tag);
|
||||
}
|
||||
|
||||
void aes_gcm256_hard_encrypt(gcm_context_t *context, uint8_t *input_data, size_t input_len, uint8_t *output_data, uint8_t *gcm_tag)
|
||||
{
|
||||
aes_init(context->input_key, AES_256, context->iv, IV_LEN_96, context->gcm_aad,
|
||||
AES_GCM, AES_HARD_ENCRYPTION, context->gcm_aad_len, input_len);
|
||||
aes_process(input_data, output_data, input_len, AES_GCM);
|
||||
gcm_get_tag(gcm_tag);
|
||||
}
|
||||
|
||||
void aes_ecb128_hard_decrypt_dma(dmac_channel_number_t dma_receive_channel_num,
|
||||
uint8_t *input_key,
|
||||
uint8_t *input_data,
|
||||
size_t input_len,
|
||||
uint8_t *output_data)
|
||||
{
|
||||
size_t padding_len = ((input_len + 15) / 16) * 16;
|
||||
aes_init(input_key, AES_128, NULL, 0L, NULL, AES_ECB, AES_HARD_DECRYPTION, 0L, input_len);
|
||||
|
||||
sysctl_dma_select(dma_receive_channel_num, SYSCTL_DMA_SELECT_AES_REQ);
|
||||
aes->dma_sel = 1;
|
||||
dmac_set_single_mode(dma_receive_channel_num, (void *)(&aes->aes_out_data), output_data, DMAC_ADDR_NOCHANGE, DMAC_ADDR_INCREMENT,
|
||||
DMAC_MSIZE_4, DMAC_TRANS_WIDTH_32, padding_len >> 2);
|
||||
aes_input_bytes(input_data, input_len, AES_ECB);
|
||||
|
||||
dmac_wait_done(dma_receive_channel_num);
|
||||
}
|
||||
|
||||
|
||||
void aes_ecb128_hard_encrypt_dma(dmac_channel_number_t dma_receive_channel_num,
|
||||
uint8_t *input_key,
|
||||
uint8_t *input_data,
|
||||
size_t input_len,
|
||||
uint8_t *output_data)
|
||||
{
|
||||
aes_init(input_key, AES_128, NULL, 0L, NULL, AES_ECB, AES_HARD_ENCRYPTION, 0L, input_len);
|
||||
size_t padding_len = ((input_len + 15) / 16) * 16;
|
||||
|
||||
sysctl_dma_select(dma_receive_channel_num, SYSCTL_DMA_SELECT_AES_REQ);
|
||||
aes->dma_sel = 1;
|
||||
dmac_set_single_mode(dma_receive_channel_num, (void *)(&aes->aes_out_data), output_data, DMAC_ADDR_NOCHANGE, DMAC_ADDR_INCREMENT,
|
||||
DMAC_MSIZE_4, DMAC_TRANS_WIDTH_32, padding_len >> 2);
|
||||
aes_input_bytes(input_data, input_len, AES_ECB);
|
||||
dmac_wait_done(dma_receive_channel_num);
|
||||
}
|
||||
|
||||
void aes_ecb192_hard_decrypt_dma(dmac_channel_number_t dma_receive_channel_num,
|
||||
uint8_t *input_key,
|
||||
uint8_t *input_data,
|
||||
size_t input_len,
|
||||
uint8_t *output_data)
|
||||
{
|
||||
size_t padding_len = ((input_len + 15) / 16) * 16;
|
||||
aes_init(input_key, AES_192, NULL, 0L, NULL, AES_ECB, AES_HARD_DECRYPTION, 0L, input_len);
|
||||
|
||||
sysctl_dma_select(dma_receive_channel_num, SYSCTL_DMA_SELECT_AES_REQ);
|
||||
aes->dma_sel = 1;
|
||||
dmac_set_single_mode(dma_receive_channel_num, (void *)(&aes->aes_out_data), output_data, DMAC_ADDR_NOCHANGE, DMAC_ADDR_INCREMENT,
|
||||
DMAC_MSIZE_4, DMAC_TRANS_WIDTH_32, padding_len >> 2);
|
||||
aes_input_bytes(input_data, input_len, AES_ECB);
|
||||
dmac_wait_done(dma_receive_channel_num);
|
||||
}
|
||||
|
||||
void aes_ecb192_hard_encrypt_dma(dmac_channel_number_t dma_receive_channel_num,
|
||||
uint8_t *input_key,
|
||||
uint8_t *input_data,
|
||||
size_t input_len,
|
||||
uint8_t *output_data)
|
||||
{
|
||||
aes_init(input_key, AES_192, NULL, 0L, NULL, AES_ECB, AES_HARD_ENCRYPTION, 0L, input_len);
|
||||
size_t padding_len = ((input_len + 15) / 16) * 16;
|
||||
|
||||
sysctl_dma_select(dma_receive_channel_num, SYSCTL_DMA_SELECT_AES_REQ);
|
||||
aes->dma_sel = 1;
|
||||
dmac_set_single_mode(dma_receive_channel_num, (void *)(&aes->aes_out_data), output_data, DMAC_ADDR_NOCHANGE, DMAC_ADDR_INCREMENT,
|
||||
DMAC_MSIZE_4, DMAC_TRANS_WIDTH_32, padding_len >> 2);
|
||||
aes_input_bytes(input_data, input_len, AES_ECB);
|
||||
dmac_wait_done(dma_receive_channel_num);
|
||||
}
|
||||
|
||||
void aes_ecb256_hard_decrypt_dma(dmac_channel_number_t dma_receive_channel_num,
|
||||
uint8_t *input_key,
|
||||
uint8_t *input_data,
|
||||
size_t input_len,
|
||||
uint8_t *output_data)
|
||||
{
|
||||
size_t padding_len = ((input_len + 15) / 16) * 16;
|
||||
aes_init(input_key, AES_256, NULL, 0L, NULL, AES_ECB, AES_HARD_DECRYPTION, 0L, input_len);
|
||||
|
||||
sysctl_dma_select(dma_receive_channel_num, SYSCTL_DMA_SELECT_AES_REQ);
|
||||
aes->dma_sel = 1;
|
||||
dmac_set_single_mode(dma_receive_channel_num, (void *)(&aes->aes_out_data), output_data, DMAC_ADDR_NOCHANGE, DMAC_ADDR_INCREMENT,
|
||||
DMAC_MSIZE_4, DMAC_TRANS_WIDTH_32, padding_len >> 2);
|
||||
aes_input_bytes(input_data, input_len, AES_ECB);
|
||||
dmac_wait_done(dma_receive_channel_num);
|
||||
}
|
||||
|
||||
void aes_ecb256_hard_encrypt_dma(dmac_channel_number_t dma_receive_channel_num,
|
||||
uint8_t *input_key,
|
||||
uint8_t *input_data,
|
||||
size_t input_len,
|
||||
uint8_t *output_data)
|
||||
{
|
||||
aes_init(input_key, AES_256, NULL, 0L, NULL, AES_ECB, AES_HARD_ENCRYPTION, 0L, input_len);
|
||||
size_t padding_len = ((input_len + 15) / 16) * 16;
|
||||
|
||||
sysctl_dma_select(dma_receive_channel_num, SYSCTL_DMA_SELECT_AES_REQ);
|
||||
aes->dma_sel = 1;
|
||||
dmac_set_single_mode(dma_receive_channel_num, (void *)(&aes->aes_out_data), output_data, DMAC_ADDR_NOCHANGE, DMAC_ADDR_INCREMENT,
|
||||
DMAC_MSIZE_4, DMAC_TRANS_WIDTH_32, padding_len >> 2);
|
||||
aes_input_bytes(input_data, input_len, AES_ECB);
|
||||
|
||||
dmac_wait_done(dma_receive_channel_num);
|
||||
}
|
||||
|
||||
void aes_cbc128_hard_decrypt_dma(dmac_channel_number_t dma_receive_channel_num,
|
||||
cbc_context_t *context,
|
||||
uint8_t *input_data,
|
||||
size_t input_len,
|
||||
uint8_t *output_data)
|
||||
{
|
||||
size_t padding_len = ((input_len + 15) / 16) * 16;
|
||||
aes_init(context->input_key, AES_128, context->iv, IV_LEN_128, NULL, AES_CBC, AES_HARD_DECRYPTION, 0L, input_len);
|
||||
|
||||
sysctl_dma_select(dma_receive_channel_num, SYSCTL_DMA_SELECT_AES_REQ);
|
||||
aes->dma_sel = 1;
|
||||
dmac_set_single_mode(dma_receive_channel_num, (void *)(&aes->aes_out_data), output_data, DMAC_ADDR_NOCHANGE, DMAC_ADDR_INCREMENT,
|
||||
DMAC_MSIZE_4, DMAC_TRANS_WIDTH_32, padding_len >> 2);
|
||||
aes_input_bytes(input_data, input_len, AES_CBC);
|
||||
dmac_wait_done(dma_receive_channel_num);
|
||||
}
|
||||
|
||||
void aes_cbc128_hard_encrypt_dma(dmac_channel_number_t dma_receive_channel_num,
|
||||
cbc_context_t *context,
|
||||
uint8_t *input_data,
|
||||
size_t input_len,
|
||||
uint8_t *output_data)
|
||||
{
|
||||
aes_init(context->input_key, AES_128, context->iv, IV_LEN_128, NULL, AES_CBC, AES_HARD_ENCRYPTION, 0L, input_len);
|
||||
size_t padding_len = ((input_len + 15) / 16) * 16;
|
||||
|
||||
sysctl_dma_select(dma_receive_channel_num, SYSCTL_DMA_SELECT_AES_REQ);
|
||||
aes->dma_sel = 1;
|
||||
dmac_set_single_mode(dma_receive_channel_num, (void *)(&aes->aes_out_data), output_data, DMAC_ADDR_NOCHANGE, DMAC_ADDR_INCREMENT,
|
||||
DMAC_MSIZE_4, DMAC_TRANS_WIDTH_32, padding_len >> 2);
|
||||
aes_input_bytes(input_data, input_len, AES_CBC);
|
||||
dmac_wait_done(dma_receive_channel_num);
|
||||
}
|
||||
|
||||
void aes_cbc192_hard_decrypt_dma(dmac_channel_number_t dma_receive_channel_num,
|
||||
cbc_context_t *context,
|
||||
uint8_t *input_data,
|
||||
size_t input_len,
|
||||
uint8_t *output_data)
|
||||
{
|
||||
size_t padding_len = ((input_len + 15) / 16) * 16;
|
||||
aes_init(context->input_key, AES_192, context->iv, IV_LEN_128, NULL, AES_CBC, AES_HARD_DECRYPTION, 0L, input_len);
|
||||
|
||||
sysctl_dma_select(dma_receive_channel_num, SYSCTL_DMA_SELECT_AES_REQ);
|
||||
aes->dma_sel = 1;
|
||||
dmac_set_single_mode(dma_receive_channel_num, (void *)(&aes->aes_out_data), output_data, DMAC_ADDR_NOCHANGE, DMAC_ADDR_INCREMENT,
|
||||
DMAC_MSIZE_4, DMAC_TRANS_WIDTH_32, padding_len >> 2);
|
||||
aes_input_bytes(input_data, input_len, AES_CBC);
|
||||
dmac_wait_done(dma_receive_channel_num);
|
||||
}
|
||||
|
||||
void aes_cbc192_hard_encrypt_dma(dmac_channel_number_t dma_receive_channel_num,
|
||||
cbc_context_t *context,
|
||||
uint8_t *input_data,
|
||||
size_t input_len,
|
||||
uint8_t *output_data)
|
||||
{
|
||||
aes_init(context->input_key, AES_192, context->iv, IV_LEN_128, NULL, AES_CBC, AES_HARD_ENCRYPTION, 0L, input_len);
|
||||
size_t padding_len = ((input_len + 15) / 16) * 16;
|
||||
|
||||
sysctl_dma_select(dma_receive_channel_num, SYSCTL_DMA_SELECT_AES_REQ);
|
||||
aes->dma_sel = 1;
|
||||
dmac_set_single_mode(dma_receive_channel_num, (void *)(&aes->aes_out_data), output_data, DMAC_ADDR_NOCHANGE, DMAC_ADDR_INCREMENT,
|
||||
DMAC_MSIZE_4, DMAC_TRANS_WIDTH_32, padding_len >> 2);
|
||||
aes_input_bytes(input_data, input_len, AES_CBC);
|
||||
dmac_wait_done(dma_receive_channel_num);
|
||||
}
|
||||
|
||||
void aes_cbc256_hard_decrypt_dma(dmac_channel_number_t dma_receive_channel_num,
|
||||
cbc_context_t *context,
|
||||
uint8_t *input_data,
|
||||
size_t input_len,
|
||||
uint8_t *output_data)
|
||||
{
|
||||
size_t padding_len = ((input_len + 15) / 16) * 16;
|
||||
aes_init(context->input_key, AES_256, context->iv, IV_LEN_128, NULL, AES_CBC, AES_HARD_DECRYPTION, 0L, input_len);
|
||||
|
||||
sysctl_dma_select(dma_receive_channel_num, SYSCTL_DMA_SELECT_AES_REQ);
|
||||
aes->dma_sel = 1;
|
||||
dmac_set_single_mode(dma_receive_channel_num, (void *)(&aes->aes_out_data), output_data, DMAC_ADDR_NOCHANGE, DMAC_ADDR_INCREMENT,
|
||||
DMAC_MSIZE_4, DMAC_TRANS_WIDTH_32, padding_len >> 2);
|
||||
aes_input_bytes(input_data, input_len, AES_CBC);
|
||||
dmac_wait_done(dma_receive_channel_num);
|
||||
}
|
||||
|
||||
void aes_cbc256_hard_encrypt_dma(dmac_channel_number_t dma_receive_channel_num,
|
||||
cbc_context_t *context,
|
||||
uint8_t *input_data,
|
||||
size_t input_len,
|
||||
uint8_t *output_data)
|
||||
{
|
||||
aes_init(context->input_key, AES_256, context->iv, IV_LEN_128, NULL, AES_CBC, AES_HARD_ENCRYPTION, 0L, input_len);
|
||||
size_t padding_len = ((input_len + 15) / 16) * 16;
|
||||
|
||||
sysctl_dma_select(dma_receive_channel_num, SYSCTL_DMA_SELECT_AES_REQ);
|
||||
aes->dma_sel = 1;
|
||||
dmac_set_single_mode(dma_receive_channel_num, (void *)(&aes->aes_out_data), output_data, DMAC_ADDR_NOCHANGE, DMAC_ADDR_INCREMENT,
|
||||
DMAC_MSIZE_4, DMAC_TRANS_WIDTH_32, padding_len >> 2);
|
||||
aes_input_bytes(input_data, input_len, AES_CBC);
|
||||
dmac_wait_done(dma_receive_channel_num);
|
||||
}
|
||||
|
||||
void aes_gcm128_hard_decrypt_dma(dmac_channel_number_t dma_receive_channel_num,
|
||||
gcm_context_t *context,
|
||||
uint8_t *input_data,
|
||||
size_t input_len,
|
||||
uint8_t *output_data,
|
||||
uint8_t *gcm_tag)
|
||||
{
|
||||
aes_init(context->input_key, AES_128, context->iv, IV_LEN_96, context->gcm_aad,
|
||||
AES_GCM, AES_HARD_DECRYPTION, context->gcm_aad_len, input_len);
|
||||
|
||||
sysctl_dma_select(dma_receive_channel_num, SYSCTL_DMA_SELECT_AES_REQ);
|
||||
aes->dma_sel = 1;
|
||||
dmac_set_single_mode(dma_receive_channel_num, (void *)(&aes->aes_out_data), output_data, DMAC_ADDR_NOCHANGE, DMAC_ADDR_INCREMENT,
|
||||
DMAC_MSIZE_4, DMAC_TRANS_WIDTH_32, (input_len + 3) >> 2);
|
||||
aes_input_bytes(input_data, input_len, AES_GCM);
|
||||
dmac_wait_done(dma_receive_channel_num);
|
||||
|
||||
gcm_get_tag(gcm_tag);
|
||||
}
|
||||
|
||||
void aes_gcm128_hard_encrypt_dma(dmac_channel_number_t dma_receive_channel_num,
|
||||
gcm_context_t *context,
|
||||
uint8_t *input_data,
|
||||
size_t input_len,
|
||||
uint8_t *output_data,
|
||||
uint8_t *gcm_tag)
|
||||
{
|
||||
aes_init(context->input_key, AES_128, context->iv, IV_LEN_96, context->gcm_aad,
|
||||
AES_GCM, AES_HARD_ENCRYPTION, context->gcm_aad_len, input_len);
|
||||
|
||||
sysctl_dma_select(dma_receive_channel_num, SYSCTL_DMA_SELECT_AES_REQ);
|
||||
aes->dma_sel = 1;
|
||||
dmac_set_single_mode(dma_receive_channel_num, (void *)(&aes->aes_out_data), output_data, DMAC_ADDR_NOCHANGE, DMAC_ADDR_INCREMENT,
|
||||
DMAC_MSIZE_4, DMAC_TRANS_WIDTH_32, (input_len + 3) >> 2);
|
||||
aes_input_bytes(input_data, input_len, AES_GCM);
|
||||
dmac_wait_done(dma_receive_channel_num);
|
||||
|
||||
gcm_get_tag(gcm_tag);
|
||||
}
|
||||
|
||||
void aes_gcm192_hard_decrypt_dma(dmac_channel_number_t dma_receive_channel_num,
|
||||
gcm_context_t *context,
|
||||
uint8_t *input_data,
|
||||
size_t input_len,
|
||||
uint8_t *output_data,
|
||||
uint8_t *gcm_tag)
|
||||
{
|
||||
aes_init(context->input_key, AES_192, context->iv, IV_LEN_96, context->gcm_aad,
|
||||
AES_GCM, AES_HARD_DECRYPTION, context->gcm_aad_len, input_len);
|
||||
|
||||
sysctl_dma_select(dma_receive_channel_num, SYSCTL_DMA_SELECT_AES_REQ);
|
||||
aes->dma_sel = 1;
|
||||
dmac_set_single_mode(dma_receive_channel_num, (void *)(&aes->aes_out_data), output_data, DMAC_ADDR_NOCHANGE, DMAC_ADDR_INCREMENT,
|
||||
DMAC_MSIZE_4, DMAC_TRANS_WIDTH_32, (input_len + 3) >> 2);
|
||||
aes_input_bytes(input_data, input_len, AES_GCM);
|
||||
dmac_wait_done(dma_receive_channel_num);
|
||||
|
||||
gcm_get_tag(gcm_tag);
|
||||
}
|
||||
|
||||
void aes_gcm192_hard_encrypt_dma(dmac_channel_number_t dma_receive_channel_num,
|
||||
gcm_context_t *context,
|
||||
uint8_t *input_data,
|
||||
size_t input_len,
|
||||
uint8_t *output_data,
|
||||
uint8_t *gcm_tag)
|
||||
{
|
||||
aes_init(context->input_key, AES_192, context->iv, IV_LEN_96, context->gcm_aad,
|
||||
AES_GCM, AES_HARD_ENCRYPTION, context->gcm_aad_len, input_len);
|
||||
|
||||
sysctl_dma_select(dma_receive_channel_num, SYSCTL_DMA_SELECT_AES_REQ);
|
||||
aes->dma_sel = 1;
|
||||
dmac_set_single_mode(dma_receive_channel_num, (void *)(&aes->aes_out_data), output_data, DMAC_ADDR_NOCHANGE, DMAC_ADDR_INCREMENT,
|
||||
DMAC_MSIZE_4, DMAC_TRANS_WIDTH_32, (input_len + 3) >> 2);
|
||||
aes_input_bytes(input_data, input_len, AES_GCM);
|
||||
dmac_wait_done(dma_receive_channel_num);
|
||||
|
||||
gcm_get_tag(gcm_tag);
|
||||
}
|
||||
|
||||
void aes_gcm256_hard_decrypt_dma(dmac_channel_number_t dma_receive_channel_num,
|
||||
gcm_context_t *context,
|
||||
uint8_t *input_data,
|
||||
size_t input_len,
|
||||
uint8_t *output_data,
|
||||
uint8_t *gcm_tag)
|
||||
{
|
||||
aes_init(context->input_key, AES_256, context->iv, IV_LEN_96, context->gcm_aad,
|
||||
AES_GCM, AES_HARD_DECRYPTION, context->gcm_aad_len, input_len);
|
||||
|
||||
sysctl_dma_select(dma_receive_channel_num, SYSCTL_DMA_SELECT_AES_REQ);
|
||||
aes->dma_sel = 1;
|
||||
dmac_set_single_mode(dma_receive_channel_num, (void *)(&aes->aes_out_data), output_data, DMAC_ADDR_NOCHANGE, DMAC_ADDR_INCREMENT,
|
||||
DMAC_MSIZE_4, DMAC_TRANS_WIDTH_32, (input_len + 3) >> 2);
|
||||
aes_input_bytes(input_data, input_len, AES_GCM);
|
||||
dmac_wait_done(dma_receive_channel_num);
|
||||
|
||||
gcm_get_tag(gcm_tag);
|
||||
}
|
||||
|
||||
void aes_gcm256_hard_encrypt_dma(dmac_channel_number_t dma_receive_channel_num,
|
||||
gcm_context_t *context,
|
||||
uint8_t *input_data,
|
||||
size_t input_len,
|
||||
uint8_t *output_data,
|
||||
uint8_t *gcm_tag)
|
||||
{
|
||||
aes_init(context->input_key, AES_256, context->iv, IV_LEN_96, context->gcm_aad,
|
||||
AES_GCM, AES_HARD_ENCRYPTION, context->gcm_aad_len, input_len);
|
||||
|
||||
sysctl_dma_select(dma_receive_channel_num, SYSCTL_DMA_SELECT_AES_REQ);
|
||||
aes->dma_sel = 1;
|
||||
dmac_set_single_mode(dma_receive_channel_num, (void *)(&aes->aes_out_data), output_data, DMAC_ADDR_NOCHANGE, DMAC_ADDR_INCREMENT,
|
||||
DMAC_MSIZE_4, DMAC_TRANS_WIDTH_32, (input_len + 3) >> 2);
|
||||
aes_input_bytes(input_data, input_len, AES_GCM);
|
||||
dmac_wait_done(dma_receive_channel_num);
|
||||
|
||||
gcm_get_tag(gcm_tag);
|
||||
}
|
||||
|
||||
@@ -1,513 +0,0 @@
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <math.h>
|
||||
#include "syscalls.h"
|
||||
#include "sysctl.h"
|
||||
#include "apu.h"
|
||||
|
||||
#define BEAFORMING_BASE_ADDR (0x50250200)
|
||||
#ifndef M_PI
|
||||
#define M_PI 3.14159265358979323846264338327950288
|
||||
#endif
|
||||
|
||||
volatile apu_reg_t *const apu = (volatile apu_reg_t *)BEAFORMING_BASE_ADDR;
|
||||
|
||||
/*
|
||||
Voice strength average value right shift factor. When performing sound direction detect,
|
||||
the average value of samples from different channels is required, this right shift factor
|
||||
is used to perform division.
|
||||
0x0: no right shift; 0x1: right shift by 1-bit;
|
||||
. . . . . .
|
||||
0xF: right shift by 14-bit.
|
||||
*/
|
||||
void apu_set_audio_gain(uint16_t gain)
|
||||
{
|
||||
apu_ch_cfg_t ch_cfg = apu->bf_ch_cfg_reg;
|
||||
|
||||
ch_cfg.we_bf_target_dir = 0;
|
||||
ch_cfg.we_bf_sound_ch_en = 0;
|
||||
ch_cfg.we_data_src_mode = 0;
|
||||
ch_cfg.we_audio_gain = 1;
|
||||
ch_cfg.audio_gain = gain;
|
||||
apu->bf_ch_cfg_reg = ch_cfg;
|
||||
}
|
||||
|
||||
/*set sampling shift*/
|
||||
void apu_set_smpl_shift(uint8_t smpl_shift)
|
||||
{
|
||||
apu_dwsz_cfg_t tmp = apu->bf_dwsz_cfg_reg;
|
||||
|
||||
tmp.smpl_shift_bits = smpl_shift;
|
||||
apu->bf_dwsz_cfg_reg = tmp;
|
||||
}
|
||||
/*get sampling shift*/
|
||||
uint8_t apu_get_smpl_shift(void)
|
||||
{
|
||||
apu_dwsz_cfg_t tmp = apu->bf_dwsz_cfg_reg;
|
||||
|
||||
return tmp.smpl_shift_bits;
|
||||
}
|
||||
|
||||
/*
|
||||
* BF unit sound channel enable control bits. Bit 'x' corresponds to enable bit for sound
|
||||
* channel 'x' (x = 0, 1, 2, . . ., 7). BF sound channels are related with I2S host RX channels.
|
||||
* BF sound channel 0/1 correspond to the left/right channel of I2S RX0; BF channel 2/3 correspond
|
||||
* to left/right channels of I2S RX1; and things like that. Software write '1' to enable a sound
|
||||
* channel and hardware automatically clear the bit after the sample buffers used for direction
|
||||
* searching is filled full.
|
||||
* 0x1: writing '1' to enable the corresponding BF sound channel.
|
||||
*/
|
||||
void apu_set_channel_enabled(uint8_t channel_bit)
|
||||
{
|
||||
apu_ch_cfg_t ch_cfg;
|
||||
|
||||
ch_cfg.we_audio_gain = 0;
|
||||
ch_cfg.we_bf_target_dir = 0;
|
||||
ch_cfg.we_bf_sound_ch_en = 1;
|
||||
ch_cfg.bf_sound_ch_en = channel_bit;
|
||||
apu->bf_ch_cfg_reg = ch_cfg;
|
||||
}
|
||||
|
||||
/*
|
||||
* BF unit sound channel enable control bits. Bit 'x' corresponds to enable bit for sound
|
||||
* channel 'x' (x = 0, 1, 2, . . ., 7). BF sound channels are related with I2S host RX channels.
|
||||
* BF sound channel 0/1 correspond to the left/right channel of I2S RX0; BF channel 2/3 correspond
|
||||
* to left/right channels of I2S RX1; and things like that. Software write '1' to enable a sound
|
||||
* channel and hardware automatically clear the bit after the sample buffers used for direction
|
||||
* searching is filled full.
|
||||
* 0x1: writing '1' to enable the corresponding BF sound channel.
|
||||
*/
|
||||
void apu_channel_enable(uint8_t channel_bit)
|
||||
{
|
||||
apu_ch_cfg_t ch_cfg = apu->bf_ch_cfg_reg;
|
||||
|
||||
ch_cfg.we_audio_gain = 0;
|
||||
ch_cfg.we_bf_target_dir = 0;
|
||||
ch_cfg.we_data_src_mode = 0;
|
||||
ch_cfg.we_bf_sound_ch_en = 1;
|
||||
ch_cfg.bf_sound_ch_en = channel_bit;
|
||||
apu->bf_ch_cfg_reg = ch_cfg;
|
||||
}
|
||||
|
||||
/*
|
||||
* audio data source configure parameter. This parameter controls where the audio data source comes from.
|
||||
* 0x0: audio data directly sourcing from apu internal buffer;
|
||||
* 0x1: audio data sourcing from FFT result buffer.
|
||||
*/
|
||||
void apu_set_src_mode(uint8_t src_mode)
|
||||
{
|
||||
apu_ch_cfg_t ch_cfg = apu->bf_ch_cfg_reg;
|
||||
|
||||
ch_cfg.we_audio_gain = 0;
|
||||
ch_cfg.we_bf_target_dir = 0;
|
||||
ch_cfg.we_bf_sound_ch_en = 0;
|
||||
ch_cfg.we_data_src_mode = 1;
|
||||
ch_cfg.data_src_mode = src_mode;
|
||||
apu->bf_ch_cfg_reg = ch_cfg;
|
||||
}
|
||||
|
||||
/*
|
||||
* I2S host beam-forming direction sample ibuffer read index configure register
|
||||
*/
|
||||
void apu_set_direction_delay(uint8_t dir_num, uint8_t *dir_bidx)
|
||||
{
|
||||
apu->bf_dir_bidx[dir_num][0] =(apu_dir_bidx_t)
|
||||
{
|
||||
.dir_rd_idx0 = dir_bidx[0],
|
||||
.dir_rd_idx1 = dir_bidx[1],
|
||||
.dir_rd_idx2 = dir_bidx[2],
|
||||
.dir_rd_idx3 = dir_bidx[3]
|
||||
};
|
||||
apu->bf_dir_bidx[dir_num][1] =(apu_dir_bidx_t)
|
||||
{
|
||||
.dir_rd_idx0 = dir_bidx[4],
|
||||
.dir_rd_idx1 = dir_bidx[5],
|
||||
.dir_rd_idx2 = dir_bidx[6],
|
||||
.dir_rd_idx3 = dir_bidx[7]
|
||||
};
|
||||
}
|
||||
|
||||
/*
|
||||
* radius mic_num_a_circle: the num of mic per circle; center: 0: no center mic, 1:have center mic
|
||||
*/
|
||||
void apu_set_delay(float radius, uint8_t mic_num_a_circle, uint8_t center)
|
||||
{
|
||||
uint8_t offsets[16][8];
|
||||
int i,j;
|
||||
float seta[8], delay[8], hudu_jiao;
|
||||
float cm_tick = (float)SOUND_SPEED * 100 / I2S_FS;/*distance per tick (cm)*/
|
||||
float min;
|
||||
|
||||
for (i = 0; i < mic_num_a_circle; ++i)
|
||||
{
|
||||
seta[i] = 360 * i / mic_num_a_circle;
|
||||
hudu_jiao = 2 * M_PI * seta[i] / 360;
|
||||
delay[i] = radius * (1 - cos(hudu_jiao)) / cm_tick;
|
||||
}
|
||||
if(center)
|
||||
delay[mic_num_a_circle] = radius / cm_tick;
|
||||
|
||||
for (i = 0; i < mic_num_a_circle + center; ++i)
|
||||
{
|
||||
offsets[0][i] = (int)(delay[i] + 0.5);
|
||||
}
|
||||
for(; i < 8; i++)
|
||||
offsets[0][i] = 0;
|
||||
|
||||
|
||||
for (j = 1; j < DIRECTION_RES; ++j)
|
||||
{
|
||||
for (i = 0; i < mic_num_a_circle; ++i)
|
||||
{
|
||||
seta[i] -= 360 / DIRECTION_RES;
|
||||
hudu_jiao = 2 * M_PI * seta[i] / 360;
|
||||
delay[i] = radius * (1 - cos(hudu_jiao)) / cm_tick;
|
||||
}
|
||||
if(center)
|
||||
delay[mic_num_a_circle] = radius / cm_tick;
|
||||
|
||||
min = 2 * radius;
|
||||
for (i = 0; i < mic_num_a_circle; ++i)
|
||||
{
|
||||
if(delay[i] < min)
|
||||
min = delay[i];
|
||||
}
|
||||
if(min)
|
||||
{
|
||||
for (i = 0; i < mic_num_a_circle + center; ++i)
|
||||
{
|
||||
delay[i] = delay[i] - min;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < mic_num_a_circle + center; ++i)
|
||||
{
|
||||
offsets[j][i] = (int)(delay[i] + 0.5);
|
||||
}
|
||||
for(; i < 8; i++)
|
||||
offsets[0][i] = 0;
|
||||
}
|
||||
for (size_t i = 0; i < DIRECTION_RES; i++)
|
||||
{
|
||||
apu_set_direction_delay(i, offsets[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Sound direction searching enable bit. Software writes '1' to start sound direction searching function.
|
||||
When all the sound sample buffers are filled full, this bit is cleared by hardware (this sample buffers
|
||||
are used for direction detect only).
|
||||
0x1: enable direction searching.
|
||||
*/
|
||||
void apu_dir_enable(void)
|
||||
{
|
||||
apu_ctl_t bf_en_tmp = apu->bf_ctl_reg;
|
||||
|
||||
bf_en_tmp.we_bf_dir_search_en = 1;
|
||||
bf_en_tmp.bf_dir_search_en = 1;
|
||||
apu->bf_ctl_reg = bf_en_tmp;
|
||||
}
|
||||
|
||||
void apu_dir_reset(void)
|
||||
{
|
||||
apu_ctl_t bf_en_tmp = apu->bf_ctl_reg;
|
||||
|
||||
bf_en_tmp.we_search_path_rst = 1;
|
||||
bf_en_tmp.search_path_reset = 1;
|
||||
apu->bf_ctl_reg = bf_en_tmp;
|
||||
}
|
||||
|
||||
/*
|
||||
Valid voice sample stream generation enable bit. After sound direction searching is done, software can
|
||||
configure this bit to generate a stream of voice samples for voice recognition.
|
||||
0x1: enable output of voice sample stream.
|
||||
0x0: stop the voice samlpe stream output.
|
||||
*/
|
||||
void apu_voc_enable(uint8_t enable_flag)
|
||||
{
|
||||
apu_ctl_t bf_en_tmp = apu->bf_ctl_reg;
|
||||
|
||||
bf_en_tmp.we_bf_stream_gen = 1;
|
||||
bf_en_tmp.bf_stream_gen_en = enable_flag;
|
||||
apu->bf_ctl_reg = bf_en_tmp;
|
||||
}
|
||||
|
||||
void apu_voc_reset(void)
|
||||
{
|
||||
apu_ctl_t bf_en_tmp = apu->bf_ctl_reg;
|
||||
|
||||
bf_en_tmp.we_voice_gen_path_rst = 1;
|
||||
bf_en_tmp.voice_gen_path_reset = 1;
|
||||
apu->bf_ctl_reg = bf_en_tmp;
|
||||
}
|
||||
|
||||
/*
|
||||
Target direction select for valid voice output. When the source voice direaction searching
|
||||
is done, software can use this field to select one from 16 sound directions for the following
|
||||
voice recognition
|
||||
0x0: select sound direction 0; 0x1: select sound direction 1;
|
||||
. . . . . .
|
||||
0xF: select sound direction 15.
|
||||
*/
|
||||
void apu_voc_set_direction(en_bf_dir_t direction)
|
||||
{
|
||||
apu_ch_cfg_t ch_cfg = apu->bf_ch_cfg_reg;
|
||||
|
||||
ch_cfg.we_bf_sound_ch_en = 0;
|
||||
ch_cfg.we_audio_gain = 0;
|
||||
ch_cfg.we_data_src_mode = 0;
|
||||
ch_cfg.we_bf_target_dir = 1;
|
||||
ch_cfg.bf_target_dir = direction;
|
||||
apu->bf_ch_cfg_reg = ch_cfg;
|
||||
|
||||
apu_ctl_t bf_en_tmp = apu->bf_ctl_reg;
|
||||
|
||||
bf_en_tmp.we_update_voice_dir = 1;
|
||||
bf_en_tmp.update_voice_dir = 1;
|
||||
apu->bf_ctl_reg = bf_en_tmp;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*I2S host beam-forming Filter FIR16 Coefficient Register
|
||||
*/
|
||||
void apu_dir_set_prev_fir(uint16_t *fir_coef)
|
||||
{
|
||||
uint8_t i = 0;
|
||||
|
||||
for (i = 0; i < 9; i++) {
|
||||
apu->bf_pre_fir0_coef[i] =
|
||||
(apu_fir_coef_t){
|
||||
.fir_tap0 = fir_coef[i * 2],
|
||||
.fir_tap1 = i == 8 ? 0 : fir_coef[i * 2 + 1]
|
||||
};
|
||||
}
|
||||
}
|
||||
void apu_dir_set_post_fir(uint16_t *fir_coef)
|
||||
{
|
||||
uint8_t i = 0;
|
||||
|
||||
for (i = 0; i < 9; i++) {
|
||||
apu->bf_post_fir0_coef[i] =
|
||||
(apu_fir_coef_t){
|
||||
.fir_tap0 = fir_coef[i * 2],
|
||||
.fir_tap1 = i == 8 ? 0 : fir_coef[i * 2 + 1]
|
||||
};
|
||||
}
|
||||
}
|
||||
void apu_voc_set_prev_fir(uint16_t *fir_coef)
|
||||
{
|
||||
uint8_t i = 0;
|
||||
|
||||
for (i = 0; i < 9; i++) {
|
||||
apu->bf_pre_fir1_coef[i] =
|
||||
(apu_fir_coef_t){
|
||||
.fir_tap0 = fir_coef[i * 2],
|
||||
.fir_tap1 = i == 8 ? 0 : fir_coef[i * 2 + 1]
|
||||
};
|
||||
}
|
||||
}
|
||||
void apu_voc_set_post_fir(uint16_t *fir_coef)
|
||||
{
|
||||
uint8_t i = 0;
|
||||
|
||||
for (i = 0; i < 9; i++) {
|
||||
apu->bf_post_fir1_coef[i] =
|
||||
(apu_fir_coef_t){
|
||||
.fir_tap0 = fir_coef[i * 2],
|
||||
.fir_tap1 = i == 8 ? 0 : fir_coef[i * 2 + 1]
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
void apu_set_fft_shift_factor(uint8_t enable_flag, uint16_t shift_factor)
|
||||
{
|
||||
apu->bf_fft_cfg_reg =
|
||||
(apu_fft_cfg_t){
|
||||
.fft_enable = enable_flag,
|
||||
.fft_shift_factor = shift_factor
|
||||
};
|
||||
|
||||
apu_ch_cfg_t ch_cfg = apu->bf_ch_cfg_reg;
|
||||
|
||||
ch_cfg.we_data_src_mode = 1;
|
||||
ch_cfg.data_src_mode = enable_flag;
|
||||
apu->bf_ch_cfg_reg = ch_cfg;
|
||||
}
|
||||
|
||||
void apu_dir_set_down_size(uint8_t dir_dwn_size)
|
||||
{
|
||||
apu_dwsz_cfg_t tmp = apu->bf_dwsz_cfg_reg;
|
||||
|
||||
tmp.dir_dwn_siz_rate = dir_dwn_size;
|
||||
apu->bf_dwsz_cfg_reg = tmp;
|
||||
}
|
||||
|
||||
void apu_dir_set_interrupt_mask(uint8_t dir_int_mask)
|
||||
{
|
||||
apu_int_mask_t tmp = apu->bf_int_mask_reg;
|
||||
|
||||
tmp.dir_data_rdy_msk = dir_int_mask;
|
||||
apu->bf_int_mask_reg = tmp;
|
||||
}
|
||||
|
||||
void apu_voc_set_down_size(uint8_t voc_dwn_size)
|
||||
{
|
||||
apu_dwsz_cfg_t tmp = apu->bf_dwsz_cfg_reg;
|
||||
|
||||
tmp.voc_dwn_siz_rate = voc_dwn_size;
|
||||
apu->bf_dwsz_cfg_reg = tmp;
|
||||
}
|
||||
|
||||
void apu_voc_set_interrupt_mask(uint8_t voc_int_mask)
|
||||
{
|
||||
apu_int_mask_t tmp = apu->bf_int_mask_reg;
|
||||
|
||||
tmp.voc_buf_rdy_msk = voc_int_mask;
|
||||
apu->bf_int_mask_reg = tmp;
|
||||
}
|
||||
|
||||
|
||||
void apu_set_down_size(uint8_t dir_dwn_size, uint8_t voc_dwn_size)
|
||||
{
|
||||
apu_dwsz_cfg_t tmp = apu->bf_dwsz_cfg_reg;
|
||||
|
||||
tmp.dir_dwn_siz_rate = dir_dwn_size;
|
||||
tmp.voc_dwn_siz_rate = voc_dwn_size;
|
||||
apu->bf_dwsz_cfg_reg = tmp;
|
||||
}
|
||||
|
||||
void apu_set_interrupt_mask(uint8_t dir_int_mask, uint8_t voc_int_mask)
|
||||
{
|
||||
apu->bf_int_mask_reg =
|
||||
(apu_int_mask_t){
|
||||
.dir_data_rdy_msk = dir_int_mask,
|
||||
.voc_buf_rdy_msk = voc_int_mask
|
||||
};
|
||||
}
|
||||
|
||||
void apu_dir_clear_int_state(void)
|
||||
{
|
||||
apu->bf_int_stat_reg =
|
||||
(apu_int_stat_t){
|
||||
.dir_search_data_rdy = 1
|
||||
};
|
||||
}
|
||||
|
||||
void apu_voc_clear_int_state(void)
|
||||
{
|
||||
apu->bf_int_stat_reg =
|
||||
(apu_int_stat_t){
|
||||
.voc_buf_data_rdy = 1
|
||||
};
|
||||
}
|
||||
|
||||
/* reset saturation_counter */
|
||||
void apu_voc_reset_saturation_counter(void)
|
||||
{
|
||||
apu->saturation_counter = 1<<31;
|
||||
}
|
||||
|
||||
/*get saturation counter*/
|
||||
/*heigh 16 bit is counter, low 16 bit is total.*/
|
||||
uint32_t apu_voc_get_saturation_counter(void)
|
||||
{
|
||||
return apu->saturation_counter;
|
||||
}
|
||||
|
||||
/*set saturation limit*/
|
||||
void apu_voc_set_saturation_limit(uint16_t upper, uint16_t bottom)
|
||||
{
|
||||
apu->saturation_limits = (uint32_t)bottom<<16 | upper;
|
||||
}
|
||||
|
||||
/*get saturation limit*/
|
||||
/*heigh 16 bit is counter, low 16 bit is total.*/
|
||||
uint32_t apu_voc_get_saturation_limit(void)
|
||||
{
|
||||
return apu->saturation_limits;
|
||||
}
|
||||
|
||||
static void print_fir(const char *member_name, volatile apu_fir_coef_t *pfir)
|
||||
{
|
||||
printf(" for(int i = 0; i < 9; i++){\n");
|
||||
for (int i = 0; i < 9; i++) {
|
||||
apu_fir_coef_t fir = pfir[i];
|
||||
|
||||
printf(" apu->%s[%d] = (apu_fir_coef_t){\n", member_name, i);
|
||||
printf(" .fir_tap0 = 0x%x,\n", fir.fir_tap0);
|
||||
printf(" .fir_tap1 = 0x%x\n", fir.fir_tap1);
|
||||
printf(" };\n");
|
||||
}
|
||||
printf(" }\n");
|
||||
}
|
||||
|
||||
void apu_print_setting(void)
|
||||
{
|
||||
printf("void apu_setting(void) {\n");
|
||||
apu_ch_cfg_t bf_ch_cfg_reg = apu->bf_ch_cfg_reg;
|
||||
|
||||
printf(" apu->bf_ch_cfg_reg = (apu_ch_cfg_t){\n");
|
||||
printf(" .we_audio_gain = 1, .we_bf_target_dir = 1, .we_bf_sound_ch_en = 1,\n");
|
||||
printf(" .audio_gain = 0x%x, .bf_target_dir = %d, .bf_sound_ch_en = %d, .data_src_mode = %d\n",
|
||||
bf_ch_cfg_reg.audio_gain, bf_ch_cfg_reg.bf_target_dir, bf_ch_cfg_reg.bf_sound_ch_en, bf_ch_cfg_reg.data_src_mode);
|
||||
printf(" };\n");
|
||||
|
||||
apu_ctl_t bf_ctl_reg = apu->bf_ctl_reg;
|
||||
|
||||
printf(" apu->bf_ctl_reg = (apu_ctl_t){\n");
|
||||
printf(" .we_bf_stream_gen = 1, .we_bf_dir_search_en = 1,\n");
|
||||
printf(" .bf_stream_gen_en = %d, .bf_dir_search_en = %d\n",
|
||||
bf_ctl_reg.bf_stream_gen_en, bf_ctl_reg.bf_dir_search_en);
|
||||
printf(" };\n");
|
||||
|
||||
printf(" for(int i = 0; i < 16; i++){\n");
|
||||
for (int i = 0; i < 16; i++) {
|
||||
apu_dir_bidx_t bidx0 = apu->bf_dir_bidx[i][0];
|
||||
apu_dir_bidx_t bidx1 = apu->bf_dir_bidx[i][1];
|
||||
|
||||
printf(" apu->bf_dir_bidx[%d][0] = (apu_dir_bidx_t){\n", i);
|
||||
printf(" .dir_rd_idx0 = 0x%x,\n", bidx0.dir_rd_idx0);
|
||||
printf(" .dir_rd_idx1 = 0x%x,\n", bidx0.dir_rd_idx1);
|
||||
printf(" .dir_rd_idx2 = 0x%x,\n", bidx0.dir_rd_idx2);
|
||||
printf(" .dir_rd_idx3 = 0x%x\n", bidx0.dir_rd_idx3);
|
||||
printf(" };\n");
|
||||
printf(" apu->bf_dir_bidx[%d][1] = (apu_dir_bidx_t){\n", i);
|
||||
printf(" .dir_rd_idx0 = 0x%x,\n", bidx1.dir_rd_idx0);
|
||||
printf(" .dir_rd_idx1 = 0x%x,\n", bidx1.dir_rd_idx1);
|
||||
printf(" .dir_rd_idx2 = 0x%x,\n", bidx1.dir_rd_idx2);
|
||||
printf(" .dir_rd_idx3 = 0x%x\n", bidx1.dir_rd_idx3);
|
||||
printf(" };\n");
|
||||
}
|
||||
printf(" }\n");
|
||||
|
||||
print_fir("bf_pre_fir0_coef", apu->bf_pre_fir0_coef);
|
||||
print_fir("bf_post_fir0_coef", apu->bf_post_fir0_coef);
|
||||
print_fir("bf_pre_fir1_coef", apu->bf_pre_fir1_coef);
|
||||
print_fir("bf_post_fir1_coef", apu->bf_post_fir1_coef);
|
||||
|
||||
|
||||
apu_dwsz_cfg_t bf_dwsz_cfg_reg = apu->bf_dwsz_cfg_reg;
|
||||
|
||||
printf(" apu->bf_dwsz_cfg_reg = (apu_dwsz_cfg_t){\n");
|
||||
printf(" .dir_dwn_siz_rate = %d, .voc_dwn_siz_rate = %d\n",
|
||||
bf_dwsz_cfg_reg.dir_dwn_siz_rate, bf_dwsz_cfg_reg.voc_dwn_siz_rate);
|
||||
printf(" };\n");
|
||||
|
||||
apu_fft_cfg_t bf_fft_cfg_reg = apu->bf_fft_cfg_reg;
|
||||
|
||||
printf(" apu->bf_fft_cfg_reg = (apu_fft_cfg_t){\n");
|
||||
printf(" .fft_enable = %d, .fft_shift_factor = 0x%x\n",
|
||||
bf_fft_cfg_reg.fft_enable, bf_fft_cfg_reg.fft_shift_factor);
|
||||
printf(" };\n");
|
||||
|
||||
apu_int_mask_t bf_int_mask_reg = apu->bf_int_mask_reg;
|
||||
|
||||
printf(" apu->bf_int_mask_reg = (apu_int_mask_t){\n");
|
||||
printf(" .dir_data_rdy_msk = %d, .voc_buf_rdy_msk = %d\n",
|
||||
bf_int_mask_reg.dir_data_rdy_msk, bf_int_mask_reg.voc_buf_rdy_msk);
|
||||
printf(" };\n");
|
||||
|
||||
printf("}\n");
|
||||
}
|
||||
|
||||
@@ -1,219 +0,0 @@
|
||||
/* Copyright 2018 Canaan Inc.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* http://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.
|
||||
*/
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include "encoding.h"
|
||||
#include "clint.h"
|
||||
#include "sysctl.h"
|
||||
|
||||
volatile clint_t* const clint = (volatile clint_t*)CLINT_BASE_ADDR;
|
||||
static clint_timer_instance_t clint_timer_instance[CLINT_NUM_CORES];
|
||||
static clint_ipi_instance_t clint_ipi_instance[CLINT_NUM_CORES];
|
||||
|
||||
uint64_t clint_get_time(void)
|
||||
{
|
||||
/* No difference on cores */
|
||||
return clint->mtime;
|
||||
}
|
||||
|
||||
int clint_timer_init(void)
|
||||
{
|
||||
/* Read core id */
|
||||
unsigned long core_id = current_coreid();
|
||||
/* Clear the Machine-Timer bit in MIE */
|
||||
clear_csr(mie, MIP_MTIP);
|
||||
/* Fill core's instance with original data */
|
||||
|
||||
/* clang-format off */
|
||||
clint_timer_instance[core_id] = (const clint_timer_instance_t)
|
||||
{
|
||||
.interval = 0,
|
||||
.cycles = 0,
|
||||
.single_shot = 0,
|
||||
.callback = NULL,
|
||||
.ctx = NULL,
|
||||
};
|
||||
/* clang-format on */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int clint_timer_stop(void)
|
||||
{
|
||||
/* Clear the Machine-Timer bit in MIE */
|
||||
clear_csr(mie, MIP_MTIP);
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint64_t clint_timer_get_freq(void)
|
||||
{
|
||||
/* The clock is divided by CLINT_CLOCK_DIV */
|
||||
return sysctl_clock_get_freq(SYSCTL_CLOCK_CPU) / CLINT_CLOCK_DIV;
|
||||
}
|
||||
|
||||
int clint_timer_start(uint64_t interval, int single_shot)
|
||||
{
|
||||
/* Read core id */
|
||||
unsigned long core_id = current_coreid();
|
||||
/* Set timer interval */
|
||||
if (clint_timer_set_interval(interval) != 0)
|
||||
return -1;
|
||||
/* Set timer single shot */
|
||||
if (clint_timer_set_single_shot(single_shot) != 0)
|
||||
return -1;
|
||||
/* Check settings to prevent interval is 0 */
|
||||
if (clint_timer_instance[core_id].interval == 0)
|
||||
return -1;
|
||||
/* Check settings to prevent cycles is 0 */
|
||||
if (clint_timer_instance[core_id].cycles == 0)
|
||||
return -1;
|
||||
/* Add cycle interval to mtimecmp */
|
||||
uint64_t now = clint->mtime;
|
||||
uint64_t then = now + clint_timer_instance[core_id].cycles;
|
||||
/* Set mtimecmp by core id */
|
||||
clint->mtimecmp[core_id] = then;
|
||||
/* Enable interrupts in general */
|
||||
set_csr(mstatus, MSTATUS_MIE);
|
||||
/* Enable the Machine-Timer bit in MIE */
|
||||
set_csr(mie, MIP_MTIP);
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint64_t clint_timer_get_interval(void)
|
||||
{
|
||||
/* Read core id */
|
||||
unsigned long core_id = current_coreid();
|
||||
return clint_timer_instance[core_id].interval;
|
||||
}
|
||||
|
||||
int clint_timer_set_interval(uint64_t interval)
|
||||
{
|
||||
/* Read core id */
|
||||
unsigned long core_id = current_coreid();
|
||||
/* Check parameter */
|
||||
if (interval == 0)
|
||||
return -1;
|
||||
|
||||
/* Assign user interval with Millisecond(ms) */
|
||||
clint_timer_instance[core_id].interval = interval;
|
||||
/* Convert interval to cycles */
|
||||
clint_timer_instance[core_id].cycles = interval * clint_timer_get_freq() / 1000ULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int clint_timer_get_single_shot(void)
|
||||
{
|
||||
/* Read core id */
|
||||
unsigned long core_id = current_coreid();
|
||||
/* Get single shot mode by core id */
|
||||
return clint_timer_instance[core_id].single_shot;
|
||||
}
|
||||
|
||||
int clint_timer_set_single_shot(int single_shot)
|
||||
{
|
||||
/* Read core id */
|
||||
unsigned long core_id = current_coreid();
|
||||
/* Set single shot mode by core id */
|
||||
clint_timer_instance[core_id].single_shot = single_shot;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int clint_timer_register(clint_timer_callback_t callback, void *ctx)
|
||||
{
|
||||
/* Read core id */
|
||||
unsigned long core_id = current_coreid();
|
||||
/* Set user callback function */
|
||||
clint_timer_instance[core_id].callback = callback;
|
||||
/* Assign user context */
|
||||
clint_timer_instance[core_id].ctx = ctx;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int clint_timer_unregister(void)
|
||||
{
|
||||
/* Just assign NULL to user callback function and context */
|
||||
return clint_timer_register(NULL, NULL);
|
||||
}
|
||||
|
||||
int clint_ipi_init(void)
|
||||
{
|
||||
/* Read core id */
|
||||
unsigned long core_id = current_coreid();
|
||||
/* Clear the Machine-Software bit in MIE */
|
||||
clear_csr(mie, MIP_MSIP);
|
||||
/* Fill core's instance with original data */
|
||||
/* clang-format off */
|
||||
clint_ipi_instance[core_id] = (const clint_ipi_instance_t){
|
||||
.callback = NULL,
|
||||
.ctx = NULL,
|
||||
};
|
||||
/* clang-format on */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int clint_ipi_enable(void)
|
||||
{
|
||||
/* Enable interrupts in general */
|
||||
set_csr(mstatus, MSTATUS_MIE);
|
||||
/* Set the Machine-Software bit in MIE */
|
||||
set_csr(mie, MIP_MSIP);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int clint_ipi_disable(void)
|
||||
{
|
||||
/* Clear the Machine-Software bit in MIE */
|
||||
clear_csr(mie, MIP_MSIP);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int clint_ipi_send(size_t core_id)
|
||||
{
|
||||
if (core_id >= CLINT_NUM_CORES)
|
||||
return -1;
|
||||
clint->msip[core_id].msip = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int clint_ipi_clear(size_t core_id)
|
||||
{
|
||||
if (core_id >= CLINT_NUM_CORES)
|
||||
return -1;
|
||||
if (clint->msip[core_id].msip)
|
||||
{
|
||||
clint->msip[core_id].msip = 0;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int clint_ipi_register(clint_ipi_callback_t callback, void *ctx)
|
||||
{
|
||||
/* Read core id */
|
||||
unsigned long core_id = current_coreid();
|
||||
/* Set user callback function */
|
||||
clint_ipi_instance[core_id].callback = callback;
|
||||
/* Assign user context */
|
||||
clint_ipi_instance[core_id].ctx = ctx;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int clint_ipi_unregister(void)
|
||||
{
|
||||
/* Just assign NULL to user callback function and context */
|
||||
return clint_ipi_register(NULL, NULL);
|
||||
}
|
||||
|
||||
@@ -1,792 +0,0 @@
|
||||
/* Copyright 2018 Canaan Inc.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* http://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.
|
||||
*/
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include "dmac.h"
|
||||
#include "sysctl.h"
|
||||
#include "fpioa.h"
|
||||
#include "utils.h"
|
||||
#include "plic.h"
|
||||
#include "stdlib.h"
|
||||
|
||||
volatile dmac_t *const dmac = (dmac_t *)DMAC_BASE_ADDR;
|
||||
|
||||
typedef struct _dmac_context
|
||||
{
|
||||
dmac_channel_number_t dmac_channel;
|
||||
plic_irq_callback_t callback;
|
||||
void *ctx;
|
||||
} dmac_context_t;
|
||||
|
||||
dmac_context_t dmac_context[6];
|
||||
|
||||
static int is_memory(uintptr_t address)
|
||||
{
|
||||
enum {
|
||||
mem_len = 6 * 1024 * 1024,
|
||||
mem_no_cache_len = 8 * 1024 * 1024,
|
||||
};
|
||||
return ((address >= 0x80000000) && (address < 0x80000000 + mem_len)) || ((address >= 0x40000000) && (address < 0x40000000 + mem_no_cache_len)) || (address == 0x50450040);
|
||||
}
|
||||
|
||||
uint64_t dmac_read_id(void)
|
||||
{
|
||||
return dmac->id;
|
||||
}
|
||||
|
||||
uint64_t dmac_read_version(void)
|
||||
{
|
||||
return dmac->compver;
|
||||
}
|
||||
|
||||
uint64_t dmac_read_channel_id(dmac_channel_number_t channel_num)
|
||||
{
|
||||
return dmac->channel[channel_num].axi_id;
|
||||
}
|
||||
|
||||
static void dmac_enable(void)
|
||||
{
|
||||
dmac_cfg_u_t dmac_cfg;
|
||||
|
||||
dmac_cfg.data = readq(&dmac->cfg);
|
||||
dmac_cfg.cfg.dmac_en = 1;
|
||||
dmac_cfg.cfg.int_en = 1;
|
||||
writeq(dmac_cfg.data, &dmac->cfg);
|
||||
}
|
||||
|
||||
void dmac_disable(void)
|
||||
{
|
||||
dmac_cfg_u_t dmac_cfg;
|
||||
|
||||
dmac_cfg.data = readq(&dmac->cfg);
|
||||
dmac_cfg.cfg.dmac_en = 0;
|
||||
dmac_cfg.cfg.int_en = 0;
|
||||
writeq(dmac_cfg.data, &dmac->cfg);
|
||||
}
|
||||
|
||||
void src_transaction_complete_int_enable(dmac_channel_number_t channel_num)
|
||||
{
|
||||
dmac_ch_intstatus_enable_u_t ch_intstat;
|
||||
|
||||
ch_intstat.data = readq(&dmac->channel[channel_num].intstatus_en);
|
||||
ch_intstat.ch_intstatus_enable.enable_src_transcomp_intstat = 1;
|
||||
|
||||
writeq(ch_intstat.data, &dmac->channel[channel_num].intstatus_en);
|
||||
}
|
||||
|
||||
void dmac_channel_enable(dmac_channel_number_t channel_num)
|
||||
{
|
||||
dmac_chen_u_t chen;
|
||||
|
||||
chen.data = readq(&dmac->chen);
|
||||
|
||||
switch (channel_num) {
|
||||
case DMAC_CHANNEL0:
|
||||
chen.dmac_chen.ch1_en = 1;
|
||||
chen.dmac_chen.ch1_en_we = 1;
|
||||
break;
|
||||
case DMAC_CHANNEL1:
|
||||
chen.dmac_chen.ch2_en = 1;
|
||||
chen.dmac_chen.ch2_en_we = 1;
|
||||
break;
|
||||
case DMAC_CHANNEL2:
|
||||
chen.dmac_chen.ch3_en = 1;
|
||||
chen.dmac_chen.ch3_en_we = 1;
|
||||
break;
|
||||
case DMAC_CHANNEL3:
|
||||
chen.dmac_chen.ch4_en = 1;
|
||||
chen.dmac_chen.ch4_en_we = 1;
|
||||
break;
|
||||
case DMAC_CHANNEL4:
|
||||
chen.dmac_chen.ch5_en = 1;
|
||||
chen.dmac_chen.ch5_en_we = 1;
|
||||
break;
|
||||
case DMAC_CHANNEL5:
|
||||
chen.dmac_chen.ch6_en = 1;
|
||||
chen.dmac_chen.ch6_en_we = 1;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
writeq(chen.data, &dmac->chen);
|
||||
}
|
||||
|
||||
void dmac_channel_disable(dmac_channel_number_t channel_num)
|
||||
{
|
||||
dmac_chen_u_t chen;
|
||||
|
||||
chen.data = readq(&dmac->chen);
|
||||
|
||||
switch (channel_num)
|
||||
{
|
||||
case DMAC_CHANNEL0:
|
||||
chen.dmac_chen.ch1_en = 0;
|
||||
chen.dmac_chen.ch1_en_we = 1;
|
||||
break;
|
||||
case DMAC_CHANNEL1:
|
||||
chen.dmac_chen.ch2_en = 0;
|
||||
chen.dmac_chen.ch2_en_we = 1;
|
||||
break;
|
||||
case DMAC_CHANNEL2:
|
||||
chen.dmac_chen.ch3_en = 0;
|
||||
chen.dmac_chen.ch3_en_we = 1;
|
||||
break;
|
||||
case DMAC_CHANNEL3:
|
||||
chen.dmac_chen.ch4_en = 0;
|
||||
chen.dmac_chen.ch4_en_we = 1;
|
||||
break;
|
||||
case DMAC_CHANNEL4:
|
||||
chen.dmac_chen.ch5_en = 0;
|
||||
chen.dmac_chen.ch5_en_we = 1;
|
||||
break;
|
||||
case DMAC_CHANNEL5:
|
||||
chen.dmac_chen.ch6_en = 0;
|
||||
chen.dmac_chen.ch6_en_we = 1;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
writeq(chen.data, &dmac->chen);
|
||||
}
|
||||
|
||||
int32_t dmac_check_channel_busy(dmac_channel_number_t channel_num)
|
||||
{
|
||||
int32_t ret = 0;
|
||||
dmac_chen_u_t chen_u;
|
||||
|
||||
chen_u.data = readq(&dmac->chen);
|
||||
switch (channel_num) {
|
||||
case DMAC_CHANNEL0:
|
||||
if (chen_u.dmac_chen.ch1_en == 1)
|
||||
ret = 1;
|
||||
break;
|
||||
case DMAC_CHANNEL1:
|
||||
if (chen_u.dmac_chen.ch2_en == 1)
|
||||
ret = 1;
|
||||
break;
|
||||
case DMAC_CHANNEL2:
|
||||
if (chen_u.dmac_chen.ch3_en == 1)
|
||||
ret = 1;
|
||||
break;
|
||||
case DMAC_CHANNEL3:
|
||||
if (chen_u.dmac_chen.ch4_en == 1)
|
||||
ret = 1;
|
||||
break;
|
||||
case DMAC_CHANNEL4:
|
||||
if (chen_u.dmac_chen.ch5_en == 1)
|
||||
ret = 1;
|
||||
break;
|
||||
case DMAC_CHANNEL5:
|
||||
if (chen_u.dmac_chen.ch6_en == 1)
|
||||
ret = 1;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
writeq(chen_u.data, &dmac->chen);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int32_t dmac_set_list_master_select(dmac_channel_number_t channel_num,
|
||||
dmac_src_dst_select_t sd_sel, dmac_master_number_t mst_num)
|
||||
{
|
||||
int32_t ret = 0;
|
||||
uint64_t tmp = 0;
|
||||
dmac_ch_ctl_u_t ctl;
|
||||
|
||||
ctl.data = readq(&dmac->channel[channel_num].ctl);
|
||||
ret = dmac_check_channel_busy(channel_num);
|
||||
if (ret == 0) {
|
||||
if (sd_sel == DMAC_SRC || sd_sel == DMAC_SRC_DST)
|
||||
ctl.ch_ctl.sms = mst_num;
|
||||
|
||||
if (sd_sel == DMAC_DST || sd_sel == DMAC_SRC_DST)
|
||||
ctl.ch_ctl.dms = mst_num;
|
||||
tmp |= *(uint64_t *)&dmac->channel[channel_num].ctl;
|
||||
writeq(ctl.data, &dmac->channel[channel_num].ctl);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void dmac_enable_common_interrupt_status(void)
|
||||
{
|
||||
dmac_commonreg_intstatus_enable_u_t intstatus;
|
||||
|
||||
intstatus.data = readq(&dmac->com_intstatus_en);
|
||||
intstatus.intstatus_enable.enable_slvif_dec_err_intstat = 1;
|
||||
intstatus.intstatus_enable.enable_slvif_wr2ro_err_intstat = 1;
|
||||
intstatus.intstatus_enable.enable_slvif_rd2wo_err_intstat = 1;
|
||||
intstatus.intstatus_enable.enable_slvif_wronhold_err_intstat = 1;
|
||||
intstatus.intstatus_enable.enable_slvif_undefinedreg_dec_err_intstat = 1;
|
||||
|
||||
writeq(intstatus.data, &dmac->com_intstatus_en);
|
||||
}
|
||||
|
||||
void dmac_enable_common_interrupt_signal(void)
|
||||
{
|
||||
dmac_commonreg_intsignal_enable_u_t intsignal;
|
||||
|
||||
intsignal.data = readq(&dmac->com_intsignal_en);
|
||||
intsignal.intsignal_enable.enable_slvif_dec_err_intsignal = 1;
|
||||
intsignal.intsignal_enable.enable_slvif_wr2ro_err_intsignal = 1;
|
||||
intsignal.intsignal_enable.enable_slvif_rd2wo_err_intsignal = 1;
|
||||
intsignal.intsignal_enable.enable_slvif_wronhold_err_intsignal = 1;
|
||||
intsignal.intsignal_enable.enable_slvif_undefinedreg_dec_err_intsignal = 1;
|
||||
|
||||
writeq(intsignal.data, &dmac->com_intsignal_en);
|
||||
}
|
||||
|
||||
static void dmac_enable_channel_interrupt(dmac_channel_number_t channel_num)
|
||||
{
|
||||
writeq(0xffffffff, &dmac->channel[channel_num].intclear);
|
||||
writeq(0x2, &dmac->channel[channel_num].intstatus_en);
|
||||
}
|
||||
|
||||
void dmac_disable_channel_interrupt(dmac_channel_number_t channel_num)
|
||||
{
|
||||
writeq(0, &dmac->channel[channel_num].intstatus_en);
|
||||
}
|
||||
|
||||
static void dmac_chanel_interrupt_clear(dmac_channel_number_t channel_num)
|
||||
{
|
||||
writeq(0xffffffff, &dmac->channel[channel_num].intclear);
|
||||
}
|
||||
|
||||
int dmac_set_channel_config(dmac_channel_number_t channel_num,
|
||||
dmac_channel_config_t *cfg_param)
|
||||
{
|
||||
dmac_ch_ctl_u_t ctl;
|
||||
dmac_ch_cfg_u_t cfg;
|
||||
dmac_ch_llp_u_t ch_llp;
|
||||
|
||||
if (cfg_param->ctl_sms > DMAC_MASTER2)
|
||||
return -1;
|
||||
if (cfg_param->ctl_dms > DMAC_MASTER2)
|
||||
return -1;
|
||||
if (cfg_param->ctl_src_msize > DMAC_MSIZE_256)
|
||||
return -1;
|
||||
if (cfg_param->ctl_drc_msize > DMAC_MSIZE_256)
|
||||
return -1;
|
||||
|
||||
/**
|
||||
* cfg register must configure before ts_block and
|
||||
* sar dar register
|
||||
*/
|
||||
cfg.data = readq(&dmac->channel[channel_num].cfg);
|
||||
|
||||
cfg.ch_cfg.hs_sel_src = cfg_param->cfg_hs_sel_src;
|
||||
cfg.ch_cfg.hs_sel_dst = cfg_param->cfg_hs_sel_dst;
|
||||
cfg.ch_cfg.src_hwhs_pol = cfg_param->cfg_src_hs_pol;
|
||||
cfg.ch_cfg.dst_hwhs_pol = cfg_param->cfg_dst_hs_pol;
|
||||
cfg.ch_cfg.src_per = cfg_param->cfg_src_per;
|
||||
cfg.ch_cfg.dst_per = cfg_param->cfg_dst_per;
|
||||
cfg.ch_cfg.ch_prior = cfg_param->cfg_ch_prior;
|
||||
cfg.ch_cfg.tt_fc = cfg_param->ctl_tt_fc;
|
||||
|
||||
cfg.ch_cfg.src_multblk_type = cfg_param->cfg_src_multblk_type;
|
||||
cfg.ch_cfg.dst_multblk_type = cfg_param->cfg_dst_multblk_type;
|
||||
|
||||
writeq(cfg.data, &dmac->channel[channel_num].cfg);
|
||||
|
||||
ctl.data = readq(&dmac->channel[channel_num].ctl);
|
||||
ctl.ch_ctl.sms = cfg_param->ctl_sms;
|
||||
ctl.ch_ctl.dms = cfg_param->ctl_dms;
|
||||
/* master select */
|
||||
ctl.ch_ctl.sinc = cfg_param->ctl_sinc;
|
||||
ctl.ch_ctl.dinc = cfg_param->ctl_dinc;
|
||||
/* address incrememt */
|
||||
ctl.ch_ctl.src_tr_width = cfg_param->ctl_src_tr_width;
|
||||
ctl.ch_ctl.dst_tr_width = cfg_param->ctl_dst_tr_width;
|
||||
/* transfer width */
|
||||
ctl.ch_ctl.src_msize = cfg_param->ctl_src_msize;
|
||||
ctl.ch_ctl.dst_msize = cfg_param->ctl_drc_msize;
|
||||
/* Burst transaction length */
|
||||
ctl.ch_ctl.ioc_blktfr = cfg_param->ctl_ioc_blktfr;
|
||||
/* interrupt on completion of block transfer */
|
||||
/* 0x1 enable BLOCK_TFR_DONE_IntStat field */
|
||||
|
||||
writeq(cfg_param->ctl_block_ts, &dmac->channel[channel_num].block_ts);
|
||||
/* the number of (blcok_ts +1) data of width SRC_TR_WIDTF to be */
|
||||
/* transferred in a dma block transfer */
|
||||
|
||||
dmac->channel[channel_num].sar = cfg_param->sar;
|
||||
dmac->channel[channel_num].dar = cfg_param->dar;
|
||||
|
||||
ch_llp.data = readq(&dmac->channel[channel_num].llp);
|
||||
ch_llp.llp.loc = cfg_param->llp_loc;
|
||||
ch_llp.llp.lms = cfg_param->llp_lms;
|
||||
writeq(ch_llp.data, &dmac->channel[channel_num].llp);
|
||||
writeq(ctl.data, &dmac->channel[channel_num].ctl);
|
||||
readq(&dmac->channel[channel_num].swhssrc);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dmac_set_channel_param(dmac_channel_number_t channel_num,
|
||||
const void *src, void *dest, dmac_address_increment_t src_inc, dmac_address_increment_t dest_inc,
|
||||
dmac_burst_trans_length_t dmac_burst_size,
|
||||
dmac_transfer_width_t dmac_trans_width,
|
||||
uint32_t blockSize)
|
||||
{
|
||||
dmac_ch_ctl_u_t ctl;
|
||||
dmac_ch_cfg_u_t cfg_u;
|
||||
|
||||
int mem_type_src = is_memory((uintptr_t)src), mem_type_dest = is_memory((uintptr_t)dest);
|
||||
dmac_transfer_flow_t flow_control;
|
||||
if (mem_type_src == 0 && mem_type_dest == 0)
|
||||
{
|
||||
flow_control = DMAC_PRF2PRF_DMA;
|
||||
}else if (mem_type_src == 1 && mem_type_dest == 0)
|
||||
flow_control = DMAC_MEM2PRF_DMA;
|
||||
else if (mem_type_src == 0 && mem_type_dest == 1)
|
||||
flow_control = DMAC_PRF2MEM_DMA;
|
||||
else
|
||||
flow_control = DMAC_MEM2MEM_DMA;
|
||||
|
||||
/**
|
||||
* cfg register must configure before ts_block and
|
||||
* sar dar register
|
||||
*/
|
||||
cfg_u.data = readq(&dmac->channel[channel_num].cfg);
|
||||
|
||||
cfg_u.ch_cfg.tt_fc = flow_control;
|
||||
cfg_u.ch_cfg.hs_sel_src = mem_type_src ? DMAC_HS_SOFTWARE : DMAC_HS_HARDWARE;
|
||||
cfg_u.ch_cfg.hs_sel_dst = mem_type_dest ? DMAC_HS_SOFTWARE : DMAC_HS_HARDWARE;
|
||||
cfg_u.ch_cfg.src_per = channel_num;
|
||||
cfg_u.ch_cfg.dst_per = channel_num;
|
||||
cfg_u.ch_cfg.src_multblk_type = 0;
|
||||
cfg_u.ch_cfg.dst_multblk_type = 0;
|
||||
|
||||
writeq(cfg_u.data, &dmac->channel[channel_num].cfg);
|
||||
|
||||
dmac->channel[channel_num].sar = (uint64_t)src;
|
||||
dmac->channel[channel_num].dar = (uint64_t)dest;
|
||||
|
||||
ctl.data = readq(&dmac->channel[channel_num].ctl);
|
||||
ctl.ch_ctl.sms = DMAC_MASTER1;
|
||||
ctl.ch_ctl.dms = DMAC_MASTER2;
|
||||
/* master select */
|
||||
ctl.ch_ctl.sinc = src_inc;
|
||||
ctl.ch_ctl.dinc = dest_inc;
|
||||
/* address incrememt */
|
||||
ctl.ch_ctl.src_tr_width = dmac_trans_width;
|
||||
ctl.ch_ctl.dst_tr_width = dmac_trans_width;
|
||||
/* transfer width */
|
||||
ctl.ch_ctl.src_msize = dmac_burst_size;
|
||||
ctl.ch_ctl.dst_msize = dmac_burst_size;
|
||||
|
||||
writeq(ctl.data, &dmac->channel[channel_num].ctl);
|
||||
|
||||
writeq(blockSize - 1, &dmac->channel[channel_num].block_ts);
|
||||
/*the number of (blcok_ts +1) data of width SRC_TR_WIDTF to be */
|
||||
/* transferred in a dma block transfer */
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dmac_get_channel_config(dmac_channel_number_t channel_num,
|
||||
dmac_channel_config_t *cfg_param)
|
||||
{
|
||||
dmac_ch_ctl_u_t ctl;
|
||||
dmac_ch_cfg_u_t cfg;
|
||||
dmac_ch_llp_u_t ch_llp;
|
||||
|
||||
if (cfg_param == 0)
|
||||
return -1;
|
||||
if (channel_num < DMAC_CHANNEL0 ||
|
||||
channel_num > DMAC_CHANNEL3)
|
||||
return -1;
|
||||
|
||||
ctl.data = readq(&dmac->channel[channel_num].ctl);
|
||||
|
||||
cfg_param->ctl_sms = ctl.ch_ctl.sms;
|
||||
cfg_param->ctl_dms = ctl.ch_ctl.dms;
|
||||
cfg_param->ctl_sinc = ctl.ch_ctl.sinc;
|
||||
cfg_param->ctl_dinc = ctl.ch_ctl.dinc;
|
||||
cfg_param->ctl_src_tr_width = ctl.ch_ctl.src_tr_width;
|
||||
cfg_param->ctl_dst_tr_width = ctl.ch_ctl.dst_tr_width;
|
||||
cfg_param->ctl_src_msize = ctl.ch_ctl.src_msize;
|
||||
cfg_param->ctl_drc_msize = ctl.ch_ctl.dst_msize;
|
||||
cfg_param->ctl_ioc_blktfr = ctl.ch_ctl.ioc_blktfr;
|
||||
|
||||
cfg.data = readq(&dmac->channel[channel_num].cfg);
|
||||
cfg_param->cfg_hs_sel_src = cfg.ch_cfg.hs_sel_src;
|
||||
cfg_param->cfg_hs_sel_dst = cfg.ch_cfg.hs_sel_dst;
|
||||
cfg_param->cfg_src_hs_pol = cfg.ch_cfg.src_hwhs_pol;
|
||||
cfg_param->cfg_dst_hs_pol = cfg.ch_cfg.dst_hwhs_pol;
|
||||
cfg_param->cfg_src_per = cfg.ch_cfg.src_per;
|
||||
cfg_param->cfg_dst_per = cfg.ch_cfg.dst_per;
|
||||
cfg_param->cfg_ch_prior = cfg.ch_cfg.ch_prior;
|
||||
cfg_param->cfg_src_multblk_type = cfg.ch_cfg.src_multblk_type;
|
||||
cfg_param->cfg_dst_multblk_type = cfg.ch_cfg.dst_multblk_type;
|
||||
|
||||
cfg_param->sar = dmac->channel[channel_num].sar;
|
||||
cfg_param->dar = dmac->channel[channel_num].dar;
|
||||
|
||||
ch_llp.data = readq(&dmac->channel[channel_num].llp);
|
||||
cfg_param->llp_loc = ch_llp.llp.loc;
|
||||
cfg_param->llp_lms = ch_llp.llp.lms;
|
||||
|
||||
cfg_param->ctl_block_ts = readq(&dmac->channel[channel_num].block_ts);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void dmac_set_address(dmac_channel_number_t channel_num, uint64_t src_addr,
|
||||
uint64_t dst_addr)
|
||||
{
|
||||
writeq(src_addr, &dmac->channel[channel_num].sar);
|
||||
writeq(dst_addr, &dmac->channel[channel_num].dar);
|
||||
}
|
||||
|
||||
void dmac_set_block_ts(dmac_channel_number_t channel_num,
|
||||
uint32_t block_size)
|
||||
{
|
||||
uint32_t block_ts;
|
||||
|
||||
block_ts = block_size & 0x3fffff;
|
||||
writeq(block_ts, &dmac->channel[channel_num].block_ts);
|
||||
}
|
||||
|
||||
void dmac_source_control(dmac_channel_number_t channel_num,
|
||||
dmac_master_number_t master_select,
|
||||
dmac_address_increment_t address_mode,
|
||||
dmac_transfer_width_t tr_width,
|
||||
dmac_burst_trans_length_t burst_length)
|
||||
{
|
||||
dmac_ch_ctl_u_t ctl_u;
|
||||
|
||||
ctl_u.data = readq(&dmac->channel[channel_num].ctl);
|
||||
ctl_u.ch_ctl.sms = master_select;
|
||||
ctl_u.ch_ctl.sinc = address_mode;
|
||||
ctl_u.ch_ctl.src_tr_width = tr_width;
|
||||
ctl_u.ch_ctl.src_msize = burst_length;
|
||||
|
||||
writeq(ctl_u.data, &dmac->channel[channel_num].ctl);
|
||||
}
|
||||
|
||||
void dmac_master_control(dmac_channel_number_t channel_num,
|
||||
dmac_master_number_t master_select,
|
||||
dmac_address_increment_t address_mode,
|
||||
dmac_transfer_width_t tr_width,
|
||||
dmac_burst_trans_length_t burst_length)
|
||||
{
|
||||
dmac_ch_ctl_u_t ctl_u;
|
||||
|
||||
ctl_u.data = readq(&dmac->channel[channel_num].ctl);
|
||||
ctl_u.ch_ctl.dms = master_select;
|
||||
ctl_u.ch_ctl.dinc = address_mode;
|
||||
ctl_u.ch_ctl.dst_tr_width = tr_width;
|
||||
ctl_u.ch_ctl.dst_msize = burst_length;
|
||||
|
||||
writeq(ctl_u.data, &dmac->channel[channel_num].ctl);
|
||||
}
|
||||
|
||||
void dmac_set_source_transfer_control(dmac_channel_number_t channel_num,
|
||||
dmac_multiblk_transfer_type_t transfer_type,
|
||||
dmac_sw_hw_hs_select_t handshak_select)
|
||||
{
|
||||
dmac_ch_cfg_u_t cfg_u;
|
||||
|
||||
cfg_u.data = readq(&dmac->channel[channel_num].cfg);
|
||||
cfg_u.ch_cfg.src_multblk_type = transfer_type;
|
||||
cfg_u.ch_cfg.hs_sel_src = handshak_select;
|
||||
|
||||
writeq(cfg_u.data, &dmac->channel[channel_num].cfg);
|
||||
}
|
||||
|
||||
void dmac_set_destination_transfer_control(dmac_channel_number_t channel_num,
|
||||
dmac_multiblk_transfer_type_t transfer_type,
|
||||
dmac_sw_hw_hs_select_t handshak_select)
|
||||
{
|
||||
dmac_ch_cfg_u_t cfg_u;
|
||||
|
||||
cfg_u.data = readq(&dmac->channel[channel_num].cfg);
|
||||
cfg_u.ch_cfg.dst_multblk_type = transfer_type;
|
||||
cfg_u.ch_cfg.hs_sel_dst = handshak_select;
|
||||
|
||||
writeq(cfg_u.data, &dmac->channel[channel_num].cfg);
|
||||
}
|
||||
|
||||
void dmac_set_flow_control(dmac_channel_number_t channel_num,
|
||||
dmac_transfer_flow_t flow_control)
|
||||
{
|
||||
dmac_ch_cfg_u_t cfg_u;
|
||||
|
||||
cfg_u.data = readq(&dmac->channel[channel_num].cfg);
|
||||
cfg_u.ch_cfg.tt_fc = flow_control;
|
||||
|
||||
writeq(cfg_u.data, &dmac->channel[channel_num].cfg);
|
||||
}
|
||||
|
||||
void dmac_set_linked_list_addr_point(dmac_channel_number_t channel_num,
|
||||
uint64_t *addr)
|
||||
{
|
||||
dmac_ch_llp_u_t llp_u;
|
||||
|
||||
llp_u.data = readq(&dmac->channel[channel_num].llp);
|
||||
/* Cast pointer to uint64_t */
|
||||
llp_u.llp.loc = (uint64_t)addr;
|
||||
writeq(llp_u.data, &dmac->channel[channel_num].llp);
|
||||
}
|
||||
|
||||
void dmac_init(void)
|
||||
{
|
||||
uint64_t tmp;
|
||||
dmac_commonreg_intclear_u_t intclear;
|
||||
dmac_cfg_u_t dmac_cfg;
|
||||
dmac_reset_u_t dmac_reset;
|
||||
|
||||
sysctl_clock_enable(SYSCTL_CLOCK_DMA);
|
||||
|
||||
dmac_reset.data = readq(&dmac->reset);
|
||||
dmac_reset.reset.rst = 1;
|
||||
writeq(dmac_reset.data, &dmac->reset);
|
||||
while (dmac_reset.reset.rst)
|
||||
dmac_reset.data = readq(&dmac->reset);
|
||||
|
||||
/*reset dmac */
|
||||
|
||||
intclear.data = readq(&dmac->com_intclear);
|
||||
intclear.com_intclear.cear_slvif_dec_err_intstat = 1;
|
||||
intclear.com_intclear.clear_slvif_wr2ro_err_intstat = 1;
|
||||
intclear.com_intclear.clear_slvif_rd2wo_err_intstat = 1;
|
||||
intclear.com_intclear.clear_slvif_wronhold_err_intstat = 1;
|
||||
intclear.com_intclear.clear_slvif_undefinedreg_dec_err_intstat = 1;
|
||||
writeq(intclear.data, &dmac->com_intclear);
|
||||
/* clear common register interrupt */
|
||||
|
||||
dmac_cfg.data = readq(&dmac->cfg);
|
||||
dmac_cfg.cfg.dmac_en = 0;
|
||||
dmac_cfg.cfg.int_en = 0;
|
||||
writeq(dmac_cfg.data, &dmac->cfg);
|
||||
/* disable dmac and disable interrupt */
|
||||
|
||||
while (readq(&dmac->cfg))
|
||||
;
|
||||
tmp = readq(&dmac->chen);
|
||||
tmp &= ~0xf;
|
||||
writeq(tmp, &dmac->chen);
|
||||
/* disable all channel before configure */
|
||||
dmac_enable();
|
||||
}
|
||||
|
||||
static void list_add(struct list_head_t *new, struct list_head_t *prev,
|
||||
struct list_head_t *next)
|
||||
{
|
||||
next->prev = new;
|
||||
new->next = next;
|
||||
new->prev = prev;
|
||||
prev->next = new;
|
||||
}
|
||||
|
||||
void list_add_tail(struct list_head_t *new, struct list_head_t *head)
|
||||
{
|
||||
list_add(new, head->prev, head);
|
||||
}
|
||||
|
||||
void INIT_LIST_HEAD(struct list_head_t *list)
|
||||
{
|
||||
list->next = list;
|
||||
list->prev = list;
|
||||
}
|
||||
|
||||
void dmac_link_list_item(dmac_channel_number_t channel_num,
|
||||
uint8_t LLI_row_num, int8_t LLI_last_row,
|
||||
dmac_lli_item_t *lli_item,
|
||||
dmac_channel_config_t *cfg_param)
|
||||
{
|
||||
dmac_ch_ctl_u_t ctl;
|
||||
dmac_ch_llp_u_t llp_u;
|
||||
|
||||
lli_item[LLI_row_num].sar = cfg_param->sar;
|
||||
lli_item[LLI_row_num].dar = cfg_param->dar;
|
||||
|
||||
ctl.data = readq(&dmac->channel[channel_num].ctl);
|
||||
ctl.ch_ctl.sms = cfg_param->ctl_sms;
|
||||
ctl.ch_ctl.dms = cfg_param->ctl_dms;
|
||||
ctl.ch_ctl.sinc = cfg_param->ctl_sinc;
|
||||
ctl.ch_ctl.dinc = cfg_param->ctl_dinc;
|
||||
ctl.ch_ctl.src_tr_width = cfg_param->ctl_src_tr_width;
|
||||
ctl.ch_ctl.dst_tr_width = cfg_param->ctl_dst_tr_width;
|
||||
ctl.ch_ctl.src_msize = cfg_param->ctl_src_msize;
|
||||
ctl.ch_ctl.dst_msize = cfg_param->ctl_drc_msize;
|
||||
ctl.ch_ctl.src_stat_en = cfg_param->ctl_src_stat_en;
|
||||
ctl.ch_ctl.dst_stat_en = cfg_param->ctl_dst_stat_en;
|
||||
|
||||
if (LLI_last_row != LAST_ROW) {
|
||||
ctl.ch_ctl.shadowreg_or_lli_valid = 1;
|
||||
ctl.ch_ctl.shadowreg_or_lli_last = 0;
|
||||
} else {
|
||||
ctl.ch_ctl.shadowreg_or_lli_valid = 1;
|
||||
ctl.ch_ctl.shadowreg_or_lli_last = 1;
|
||||
}
|
||||
|
||||
lli_item[LLI_row_num].ctl = ctl.data;
|
||||
|
||||
lli_item[LLI_row_num].ch_block_ts = cfg_param->ctl_block_ts;
|
||||
lli_item[LLI_row_num].sstat = 0;
|
||||
lli_item[LLI_row_num].dstat = 0;
|
||||
|
||||
llp_u.data = readq(&dmac->channel[channel_num].llp);
|
||||
|
||||
if (LLI_last_row != LAST_ROW)
|
||||
llp_u.llp.loc = ((uint64_t)&lli_item[LLI_row_num + 1]) >> 6;
|
||||
else
|
||||
llp_u.llp.loc = 0;
|
||||
|
||||
lli_item[LLI_row_num].llp = llp_u.data;
|
||||
}
|
||||
|
||||
void dmac_update_shandow_register(dmac_channel_number_t channel_num,
|
||||
int8_t last_block, dmac_channel_config_t *cfg_param)
|
||||
{
|
||||
dmac_ch_ctl_u_t ctl_u;
|
||||
|
||||
do {
|
||||
ctl_u.data = readq(&dmac->channel[channel_num].ctl);
|
||||
} while (ctl_u.ch_ctl.shadowreg_or_lli_valid);
|
||||
|
||||
writeq(cfg_param->sar, &dmac->channel[channel_num].sar);
|
||||
writeq(cfg_param->dar, &dmac->channel[channel_num].dar);
|
||||
writeq(cfg_param->ctl_block_ts, &dmac->channel[channel_num].block_ts);
|
||||
|
||||
ctl_u.ch_ctl.sms = cfg_param->ctl_sms;
|
||||
ctl_u.ch_ctl.dms = cfg_param->ctl_dms;
|
||||
ctl_u.ch_ctl.sinc = cfg_param->ctl_sinc;
|
||||
ctl_u.ch_ctl.dinc = cfg_param->ctl_dinc;
|
||||
ctl_u.ch_ctl.src_tr_width = cfg_param->ctl_src_tr_width;
|
||||
ctl_u.ch_ctl.dst_tr_width = cfg_param->ctl_dst_tr_width;
|
||||
ctl_u.ch_ctl.src_msize = cfg_param->ctl_src_msize;
|
||||
ctl_u.ch_ctl.dst_msize = cfg_param->ctl_drc_msize;
|
||||
ctl_u.ch_ctl.src_stat_en = cfg_param->ctl_src_stat_en;
|
||||
ctl_u.ch_ctl.dst_stat_en = cfg_param->ctl_dst_stat_en;
|
||||
if (last_block != LAST_ROW)
|
||||
{
|
||||
ctl_u.ch_ctl.shadowreg_or_lli_valid = 1;
|
||||
ctl_u.ch_ctl.shadowreg_or_lli_last = 0;
|
||||
} else {
|
||||
ctl_u.ch_ctl.shadowreg_or_lli_valid = 1;
|
||||
ctl_u.ch_ctl.shadowreg_or_lli_last = 1;
|
||||
}
|
||||
|
||||
writeq(ctl_u.data, &dmac->channel[channel_num].ctl);
|
||||
writeq(0, &dmac->channel[channel_num].blk_tfr);
|
||||
}
|
||||
|
||||
void dmac_set_shadow_invalid_flag(dmac_channel_number_t channel_num)
|
||||
{
|
||||
dmac_ch_ctl_u_t ctl_u;
|
||||
|
||||
ctl_u.data = readq(&dmac->channel[channel_num].ctl);
|
||||
ctl_u.ch_ctl.shadowreg_or_lli_valid = 1;
|
||||
ctl_u.ch_ctl.shadowreg_or_lli_last = 0;
|
||||
writeq(ctl_u.data, &dmac->channel[channel_num].ctl);
|
||||
}
|
||||
|
||||
void dmac_set_single_mode(dmac_channel_number_t channel_num,
|
||||
const void *src, void *dest, dmac_address_increment_t src_inc,
|
||||
dmac_address_increment_t dest_inc,
|
||||
dmac_burst_trans_length_t dmac_burst_size,
|
||||
dmac_transfer_width_t dmac_trans_width,
|
||||
size_t block_size) {
|
||||
dmac_chanel_interrupt_clear(channel_num);
|
||||
dmac_channel_disable(channel_num);
|
||||
dmac_wait_idle(channel_num);
|
||||
dmac_set_channel_param(channel_num, src, dest, src_inc, dest_inc,
|
||||
dmac_burst_size, dmac_trans_width, block_size);
|
||||
dmac_enable();
|
||||
dmac_channel_enable(channel_num);
|
||||
}
|
||||
|
||||
int dmac_is_done(dmac_channel_number_t channel_num)
|
||||
{
|
||||
if(readq(&dmac->channel[channel_num].intstatus) & 0x2)
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
void dmac_wait_done(dmac_channel_number_t channel_num)
|
||||
{
|
||||
dmac_wait_idle(channel_num);
|
||||
}
|
||||
|
||||
int dmac_is_idle(dmac_channel_number_t channel_num)
|
||||
{
|
||||
dmac_chen_u_t chen;
|
||||
chen.data = readq(&dmac->chen);
|
||||
if((chen.data >> channel_num) & 0x1UL)
|
||||
return 0;
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
|
||||
void dmac_wait_idle(dmac_channel_number_t channel_num)
|
||||
{
|
||||
while(!dmac_is_idle(channel_num));
|
||||
dmac_chanel_interrupt_clear(channel_num); /* clear interrupt */
|
||||
}
|
||||
|
||||
void dmac_set_src_dest_length(dmac_channel_number_t channel_num, const void *src, void *dest, size_t len)
|
||||
{
|
||||
if(src != NULL)
|
||||
dmac->channel[channel_num].sar = (uint64_t)src;
|
||||
if(dest != NULL)
|
||||
dmac->channel[channel_num].dar = (uint64_t)dest;
|
||||
if(len > 0)
|
||||
dmac_set_block_ts(channel_num, len - 1);
|
||||
dmac_channel_enable(channel_num);
|
||||
}
|
||||
|
||||
static int dmac_irq_callback(void *ctx)
|
||||
{
|
||||
dmac_context_t *v_dmac_context = (dmac_context_t *)(ctx);
|
||||
dmac_channel_number_t v_dmac_channel = v_dmac_context->dmac_channel;
|
||||
dmac_chanel_interrupt_clear(v_dmac_channel);
|
||||
if(v_dmac_context->callback != NULL)
|
||||
v_dmac_context->callback(v_dmac_context->ctx);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void dmac_irq_register(dmac_channel_number_t channel_num , plic_irq_callback_t dmac_callback, void *ctx, uint32_t priority)
|
||||
{
|
||||
dmac_context[channel_num].dmac_channel = channel_num;
|
||||
dmac_context[channel_num].callback = dmac_callback;
|
||||
dmac_context[channel_num].ctx = ctx;
|
||||
dmac_enable_channel_interrupt(channel_num);
|
||||
plic_set_priority(IRQN_DMA0_INTERRUPT + channel_num, priority);
|
||||
plic_irq_enable(IRQN_DMA0_INTERRUPT + channel_num);
|
||||
plic_irq_register(IRQN_DMA0_INTERRUPT + channel_num, dmac_irq_callback, &dmac_context[channel_num]);
|
||||
}
|
||||
|
||||
void __attribute__((weak, alias("dmac_irq_register"))) dmac_set_irq(dmac_channel_number_t channel_num , plic_irq_callback_t dmac_callback, void *ctx, uint32_t priority);
|
||||
|
||||
void dmac_irq_unregister(dmac_channel_number_t channel_num)
|
||||
{
|
||||
dmac_context[channel_num].callback = NULL;
|
||||
dmac_context[channel_num].ctx = NULL;
|
||||
dmac_disable_channel_interrupt(channel_num);
|
||||
plic_irq_unregister(IRQN_DMA0_INTERRUPT + channel_num);
|
||||
}
|
||||
|
||||
void __attribute__((weak, alias("dmac_irq_unregister"))) dmac_free_irq(dmac_channel_number_t channel_num);
|
||||
|
||||
@@ -1,297 +0,0 @@
|
||||
/* Copyright 2018 Canaan Inc.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* http://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.
|
||||
*/
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include "dvp.h"
|
||||
#include "utils.h"
|
||||
#include "fpioa.h"
|
||||
#include "sysctl.h"
|
||||
#include <math.h>
|
||||
|
||||
volatile dvp_t* const dvp = (volatile dvp_t*)DVP_BASE_ADDR;
|
||||
static uint8_t g_sccb_reg_len = 8;
|
||||
|
||||
static void mdelay(uint32_t ms)
|
||||
{
|
||||
uint32_t i;
|
||||
|
||||
while (ms && ms--)
|
||||
{
|
||||
for (i = 0; i < 25000; i++)
|
||||
__asm__ __volatile__("nop");
|
||||
}
|
||||
}
|
||||
|
||||
static void dvp_sccb_clk_init(void)
|
||||
{
|
||||
uint32_t tmp;
|
||||
|
||||
tmp = dvp->sccb_cfg & (~(DVP_SCCB_SCL_LCNT_MASK | DVP_SCCB_SCL_HCNT_MASK));
|
||||
tmp |= DVP_SCCB_SCL_LCNT(255) | DVP_SCCB_SCL_HCNT(255);
|
||||
|
||||
dvp->sccb_cfg = tmp;
|
||||
}
|
||||
|
||||
uint32_t dvp_sccb_set_clk_rate(uint32_t clk_rate)
|
||||
{
|
||||
uint32_t tmp;
|
||||
uint32_t v_sccb_freq = sysctl_clock_get_freq(SYSCTL_CLOCK_APB1);
|
||||
uint16_t v_period_clk_cnt = round(v_sccb_freq / clk_rate / 2.0);
|
||||
if(v_period_clk_cnt > 255)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
tmp = dvp->sccb_cfg & (~(DVP_SCCB_SCL_LCNT_MASK | DVP_SCCB_SCL_HCNT_MASK));
|
||||
tmp |= DVP_SCCB_SCL_LCNT(v_period_clk_cnt) | DVP_SCCB_SCL_HCNT(v_period_clk_cnt);
|
||||
dvp->sccb_cfg = tmp;
|
||||
return sysctl_clock_get_freq(SYSCTL_CLOCK_DVP) / (v_period_clk_cnt * 2);
|
||||
}
|
||||
|
||||
static void dvp_sccb_start_transfer(void)
|
||||
{
|
||||
while (dvp->sts & DVP_STS_SCCB_EN)
|
||||
;
|
||||
dvp->sts = DVP_STS_SCCB_EN | DVP_STS_SCCB_EN_WE;
|
||||
while (dvp->sts & DVP_STS_SCCB_EN)
|
||||
;
|
||||
}
|
||||
|
||||
void dvp_sccb_send_data(uint8_t dev_addr, uint16_t reg_addr, uint8_t reg_data)
|
||||
{
|
||||
uint32_t tmp;
|
||||
|
||||
tmp = dvp->sccb_cfg & (~DVP_SCCB_BYTE_NUM_MASK);
|
||||
|
||||
(g_sccb_reg_len == 8) ? (tmp |= DVP_SCCB_BYTE_NUM_3) : (tmp |= DVP_SCCB_BYTE_NUM_4);
|
||||
|
||||
dvp->sccb_cfg = tmp;
|
||||
|
||||
if (g_sccb_reg_len == 8)
|
||||
{
|
||||
dvp->sccb_ctl = DVP_SCCB_WRITE_DATA_ENABLE | DVP_SCCB_DEVICE_ADDRESS(dev_addr) | DVP_SCCB_REG_ADDRESS(reg_addr) | DVP_SCCB_WDATA_BYTE0(reg_data);
|
||||
}
|
||||
else
|
||||
{
|
||||
dvp->sccb_ctl = DVP_SCCB_WRITE_DATA_ENABLE | DVP_SCCB_DEVICE_ADDRESS(dev_addr) | DVP_SCCB_REG_ADDRESS(reg_addr >> 8) | DVP_SCCB_WDATA_BYTE0(reg_addr & 0xff) | DVP_SCCB_WDATA_BYTE1(reg_data);
|
||||
}
|
||||
dvp_sccb_start_transfer();
|
||||
}
|
||||
|
||||
uint8_t dvp_sccb_receive_data(uint8_t dev_addr, uint16_t reg_addr)
|
||||
{
|
||||
uint32_t tmp;
|
||||
|
||||
tmp = dvp->sccb_cfg & (~DVP_SCCB_BYTE_NUM_MASK);
|
||||
|
||||
if (g_sccb_reg_len == 8)
|
||||
tmp |= DVP_SCCB_BYTE_NUM_2;
|
||||
else
|
||||
tmp |= DVP_SCCB_BYTE_NUM_3;
|
||||
|
||||
dvp->sccb_cfg = tmp;
|
||||
|
||||
if (g_sccb_reg_len == 8)
|
||||
{
|
||||
dvp->sccb_ctl = DVP_SCCB_WRITE_DATA_ENABLE | DVP_SCCB_DEVICE_ADDRESS(dev_addr) | DVP_SCCB_REG_ADDRESS(reg_addr);
|
||||
}
|
||||
else
|
||||
{
|
||||
dvp->sccb_ctl = DVP_SCCB_WRITE_DATA_ENABLE | DVP_SCCB_DEVICE_ADDRESS(dev_addr) | DVP_SCCB_REG_ADDRESS(reg_addr >> 8) | DVP_SCCB_WDATA_BYTE0(reg_addr & 0xff);
|
||||
}
|
||||
dvp_sccb_start_transfer();
|
||||
|
||||
dvp->sccb_ctl = DVP_SCCB_DEVICE_ADDRESS(dev_addr);
|
||||
|
||||
dvp_sccb_start_transfer();
|
||||
|
||||
return (uint8_t) DVP_SCCB_RDATA_BYTE(dvp->sccb_cfg);
|
||||
}
|
||||
|
||||
static void dvp_reset(void)
|
||||
{
|
||||
/* First power down */
|
||||
dvp->cmos_cfg |= DVP_CMOS_POWER_DOWN;
|
||||
mdelay(200);
|
||||
dvp->cmos_cfg &= ~DVP_CMOS_POWER_DOWN;
|
||||
mdelay(200);
|
||||
|
||||
/* Second reset */
|
||||
dvp->cmos_cfg &= ~DVP_CMOS_RESET;
|
||||
mdelay(200);
|
||||
dvp->cmos_cfg |= DVP_CMOS_RESET;
|
||||
mdelay(200);
|
||||
}
|
||||
|
||||
void dvp_init(uint8_t reg_len)
|
||||
{
|
||||
g_sccb_reg_len = reg_len;
|
||||
sysctl_clock_enable(SYSCTL_CLOCK_DVP);
|
||||
sysctl_reset(SYSCTL_RESET_DVP);
|
||||
dvp->cmos_cfg &= (~DVP_CMOS_CLK_DIV_MASK);
|
||||
dvp->cmos_cfg |= DVP_CMOS_CLK_DIV(3) | DVP_CMOS_CLK_ENABLE;
|
||||
dvp_sccb_clk_init();
|
||||
dvp_reset();
|
||||
}
|
||||
|
||||
uint32_t dvp_set_xclk_rate(uint32_t xclk_rate)
|
||||
{
|
||||
uint32_t v_apb1_clk = sysctl_clock_get_freq(SYSCTL_CLOCK_APB1);
|
||||
uint32_t v_period;
|
||||
if(v_apb1_clk > xclk_rate * 2)
|
||||
v_period = round(v_apb1_clk / (xclk_rate * 2.0)) - 1;
|
||||
else
|
||||
v_period = 0;
|
||||
if(v_period > 255)
|
||||
v_period = 255;
|
||||
dvp->cmos_cfg &= (~DVP_CMOS_CLK_DIV_MASK);
|
||||
dvp->cmos_cfg |= DVP_CMOS_CLK_DIV(v_period) | DVP_CMOS_CLK_ENABLE;
|
||||
dvp_reset();
|
||||
return v_apb1_clk / ((v_period + 1) * 2);
|
||||
}
|
||||
|
||||
void dvp_set_image_format(uint32_t format)
|
||||
{
|
||||
uint32_t tmp;
|
||||
|
||||
tmp = dvp->dvp_cfg & (~DVP_CFG_FORMAT_MASK);
|
||||
dvp->dvp_cfg = tmp | format;
|
||||
}
|
||||
|
||||
void dvp_enable_burst(void)
|
||||
{
|
||||
dvp->dvp_cfg |= DVP_CFG_BURST_SIZE_4BEATS;
|
||||
|
||||
dvp->axi &= (~DVP_AXI_GM_MLEN_MASK);
|
||||
dvp->axi |= DVP_AXI_GM_MLEN_4BYTE;
|
||||
}
|
||||
|
||||
void dvp_disable_burst(void)
|
||||
{
|
||||
dvp->dvp_cfg &= (~DVP_CFG_BURST_SIZE_4BEATS);
|
||||
|
||||
dvp->axi &= (~DVP_AXI_GM_MLEN_MASK);
|
||||
dvp->axi |= DVP_AXI_GM_MLEN_1BYTE;
|
||||
}
|
||||
|
||||
void dvp_set_image_size(uint32_t width, uint32_t height)
|
||||
{
|
||||
uint32_t tmp;
|
||||
|
||||
tmp = dvp->dvp_cfg & (~(DVP_CFG_HREF_BURST_NUM_MASK | DVP_CFG_LINE_NUM_MASK));
|
||||
|
||||
tmp |= DVP_CFG_LINE_NUM(height);
|
||||
|
||||
if (dvp->dvp_cfg & DVP_CFG_BURST_SIZE_4BEATS)
|
||||
tmp |= DVP_CFG_HREF_BURST_NUM(width / 8 / 4);
|
||||
else
|
||||
tmp |= DVP_CFG_HREF_BURST_NUM(width / 8 / 1);
|
||||
|
||||
dvp->dvp_cfg = tmp;
|
||||
}
|
||||
|
||||
void dvp_set_ai_addr(uint32_t r_addr, uint32_t g_addr, uint32_t b_addr)
|
||||
{
|
||||
dvp->r_addr = r_addr;
|
||||
dvp->g_addr = g_addr;
|
||||
dvp->b_addr = b_addr;
|
||||
}
|
||||
|
||||
void dvp_set_display_addr(uint32_t addr)
|
||||
{
|
||||
dvp->rgb_addr = addr;
|
||||
}
|
||||
|
||||
void dvp_start_frame(void)
|
||||
{
|
||||
while (!(dvp->sts & DVP_STS_FRAME_START))
|
||||
;
|
||||
dvp->sts = (DVP_STS_FRAME_START | DVP_STS_FRAME_START_WE);
|
||||
}
|
||||
|
||||
void dvp_start_convert(void)
|
||||
{
|
||||
dvp->sts = DVP_STS_DVP_EN | DVP_STS_DVP_EN_WE;
|
||||
}
|
||||
|
||||
void dvp_finish_convert(void)
|
||||
{
|
||||
while (!(dvp->sts & DVP_STS_FRAME_FINISH))
|
||||
;
|
||||
dvp->sts = DVP_STS_FRAME_FINISH | DVP_STS_FRAME_FINISH_WE;
|
||||
}
|
||||
|
||||
void dvp_get_image(void)
|
||||
{
|
||||
while (!(dvp->sts & DVP_STS_FRAME_START))
|
||||
;
|
||||
dvp->sts = DVP_STS_FRAME_START | DVP_STS_FRAME_START_WE;
|
||||
while (!(dvp->sts & DVP_STS_FRAME_START))
|
||||
;
|
||||
dvp->sts = DVP_STS_FRAME_FINISH | DVP_STS_FRAME_FINISH_WE | DVP_STS_FRAME_START | DVP_STS_FRAME_START_WE | DVP_STS_DVP_EN | DVP_STS_DVP_EN_WE;
|
||||
while (!(dvp->sts & DVP_STS_FRAME_FINISH))
|
||||
;
|
||||
}
|
||||
|
||||
void dvp_config_interrupt(uint32_t interrupt, uint8_t enable)
|
||||
{
|
||||
if (enable)
|
||||
dvp->dvp_cfg |= interrupt;
|
||||
else
|
||||
dvp->dvp_cfg &= (~interrupt);
|
||||
}
|
||||
|
||||
int dvp_get_interrupt(uint32_t interrupt)
|
||||
{
|
||||
if (dvp->sts & interrupt)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void dvp_clear_interrupt(uint32_t interrupt)
|
||||
{
|
||||
interrupt |= (interrupt << 1);
|
||||
dvp->sts |= interrupt;
|
||||
}
|
||||
|
||||
void dvp_enable_auto(void)
|
||||
{
|
||||
dvp->dvp_cfg |= DVP_CFG_AUTO_ENABLE;
|
||||
}
|
||||
|
||||
void dvp_disable_auto(void)
|
||||
{
|
||||
dvp->dvp_cfg &= (~DVP_CFG_AUTO_ENABLE);
|
||||
}
|
||||
|
||||
void dvp_set_output_enable(dvp_output_mode_t index, int enable)
|
||||
{
|
||||
configASSERT(index < 2);
|
||||
|
||||
if (index == 0)
|
||||
{
|
||||
if (enable)
|
||||
dvp->dvp_cfg |= DVP_CFG_AI_OUTPUT_ENABLE;
|
||||
else
|
||||
dvp->dvp_cfg &= ~DVP_CFG_AI_OUTPUT_ENABLE;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (enable)
|
||||
dvp->dvp_cfg |= DVP_CFG_DISPLAY_OUTPUT_ENABLE;
|
||||
else
|
||||
dvp->dvp_cfg &= ~DVP_CFG_DISPLAY_OUTPUT_ENABLE;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,68 +0,0 @@
|
||||
/* Copyright 2018 Canaan Inc.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* http://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.
|
||||
*/
|
||||
#include <stddef.h>
|
||||
#include "dmac.h"
|
||||
#include "utils.h"
|
||||
#include "sysctl.h"
|
||||
#include "fft.h"
|
||||
|
||||
static volatile fft_t *const fft = (volatile fft_t *)FFT_BASE_ADDR;
|
||||
|
||||
static void fft_init(uint8_t point, uint8_t mode, uint16_t shift, uint8_t is_dma, uint8_t input_mode, uint8_t data_mode)
|
||||
{
|
||||
fft->fft_ctrl.fft_point = point;
|
||||
fft->fft_ctrl.fft_mode = mode;
|
||||
fft->fft_ctrl.fft_shift = shift;
|
||||
fft->fft_ctrl.dma_send = is_dma;
|
||||
fft->fft_ctrl.fft_enable = 1;
|
||||
fft->fft_ctrl.fft_input_mode = input_mode;
|
||||
fft->fft_ctrl.fft_data_mode = data_mode;
|
||||
}
|
||||
|
||||
void fft_complex_uint16_dma(dmac_channel_number_t dma_send_channel_num, dmac_channel_number_t dma_receive_channel_num,
|
||||
uint16_t shift, fft_direction_t direction, const uint64_t *input, size_t point_num, uint64_t *output)
|
||||
{
|
||||
fft_point_t point = FFT_512;
|
||||
switch(point_num)
|
||||
{
|
||||
case 512:
|
||||
point = FFT_512;
|
||||
break;
|
||||
case 256:
|
||||
point = FFT_256;
|
||||
break;
|
||||
case 128:
|
||||
point = FFT_128;
|
||||
break;
|
||||
case 64:
|
||||
point = FFT_64;
|
||||
break;
|
||||
default:
|
||||
configASSERT(!"fft point error");
|
||||
break;
|
||||
}
|
||||
sysctl_clock_enable(SYSCTL_CLOCK_FFT);
|
||||
sysctl_reset(SYSCTL_RESET_FFT);
|
||||
fft_init(point, direction, shift, 1, 0, 0);
|
||||
sysctl_dma_select(dma_receive_channel_num, SYSCTL_DMA_SELECT_FFT_RX_REQ);
|
||||
sysctl_dma_select(dma_send_channel_num, SYSCTL_DMA_SELECT_FFT_TX_REQ);
|
||||
dmac_set_single_mode(dma_receive_channel_num, (void *)(&fft->fft_output_fifo), output, DMAC_ADDR_NOCHANGE, DMAC_ADDR_INCREMENT,
|
||||
DMAC_MSIZE_4, DMAC_TRANS_WIDTH_64, point_num>>1);
|
||||
dmac_set_single_mode(dma_send_channel_num, input, (void *)(&fft->fft_input_fifo), DMAC_ADDR_INCREMENT, DMAC_ADDR_NOCHANGE,
|
||||
DMAC_MSIZE_4, DMAC_TRANS_WIDTH_64, point_num>>1);
|
||||
dmac_wait_done(dma_receive_channel_num);
|
||||
}
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,79 +0,0 @@
|
||||
/* Copyright 2018 Canaan Inc.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* http://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.
|
||||
*/
|
||||
#include "gpio.h"
|
||||
#include "utils.h"
|
||||
#include "fpioa.h"
|
||||
#include "sysctl.h"
|
||||
#define GPIO_MAX_PINNO 8
|
||||
|
||||
volatile gpio_t* const gpio = (volatile gpio_t*)GPIO_BASE_ADDR;
|
||||
|
||||
int gpio_init(void)
|
||||
{
|
||||
return sysctl_clock_enable(SYSCTL_CLOCK_GPIO);
|
||||
}
|
||||
|
||||
void gpio_set_drive_mode(uint8_t pin, gpio_drive_mode_t mode)
|
||||
{
|
||||
configASSERT(pin < GPIO_MAX_PINNO);
|
||||
int io_number = fpioa_get_io_by_function(FUNC_GPIO0 + pin);
|
||||
configASSERT(io_number > 0);
|
||||
|
||||
fpioa_pull_t pull;
|
||||
uint32_t dir;
|
||||
|
||||
switch (mode)
|
||||
{
|
||||
case GPIO_DM_INPUT:
|
||||
pull = FPIOA_PULL_NONE;
|
||||
dir = 0;
|
||||
break;
|
||||
case GPIO_DM_INPUT_PULL_DOWN:
|
||||
pull = FPIOA_PULL_DOWN;
|
||||
dir = 0;
|
||||
break;
|
||||
case GPIO_DM_INPUT_PULL_UP:
|
||||
pull = FPIOA_PULL_UP;
|
||||
dir = 0;
|
||||
break;
|
||||
case GPIO_DM_OUTPUT:
|
||||
pull = FPIOA_PULL_DOWN;
|
||||
dir = 1;
|
||||
break;
|
||||
default:
|
||||
configASSERT(!"GPIO drive mode is not supported.") break;
|
||||
}
|
||||
|
||||
fpioa_set_io_pull(io_number, pull);
|
||||
set_gpio_bit(gpio->direction.u32, pin, dir);
|
||||
}
|
||||
|
||||
gpio_pin_value_t gpio_get_pin(uint8_t pin)
|
||||
{
|
||||
configASSERT(pin < GPIO_MAX_PINNO);
|
||||
uint32_t dir = get_gpio_bit(gpio->direction.u32, pin);
|
||||
volatile uint32_t *reg = dir ? gpio->data_output.u32 : gpio->data_input.u32;
|
||||
return get_gpio_bit(reg, pin);
|
||||
}
|
||||
|
||||
void gpio_set_pin(uint8_t pin, gpio_pin_value_t value)
|
||||
{
|
||||
configASSERT(pin < GPIO_MAX_PINNO);
|
||||
uint32_t dir = get_gpio_bit(gpio->direction.u32, pin);
|
||||
volatile uint32_t *reg = dir ? gpio->data_output.u32 : gpio->data_input.u32;
|
||||
configASSERT(dir == 1);
|
||||
set_gpio_bit(reg, pin, value);
|
||||
}
|
||||
|
||||
@@ -1,218 +0,0 @@
|
||||
/* Copyright 2018 Canaan Inc.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* http://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.
|
||||
*/
|
||||
#include "gpiohs.h"
|
||||
#include "utils.h"
|
||||
#include "fpioa.h"
|
||||
#include "sysctl.h"
|
||||
#define GPIOHS_MAX_PINNO 32
|
||||
|
||||
volatile gpiohs_t* const gpiohs = (volatile gpiohs_t*)GPIOHS_BASE_ADDR;
|
||||
|
||||
typedef struct _gpiohs_pin_instance
|
||||
{
|
||||
size_t pin;
|
||||
gpio_pin_edge_t edge;
|
||||
void (*callback)();
|
||||
plic_irq_callback_t gpiohs_callback;
|
||||
void *context;
|
||||
} gpiohs_pin_instance_t;
|
||||
|
||||
static gpiohs_pin_instance_t pin_instance[32];
|
||||
|
||||
void gpiohs_set_drive_mode(uint8_t pin, gpio_drive_mode_t mode)
|
||||
{
|
||||
configASSERT(pin < GPIOHS_MAX_PINNO);
|
||||
int io_number = fpioa_get_io_by_function(FUNC_GPIOHS0 + pin);
|
||||
configASSERT(io_number > 0);
|
||||
|
||||
fpioa_pull_t pull;
|
||||
uint32_t dir;
|
||||
|
||||
switch (mode)
|
||||
{
|
||||
case GPIO_DM_INPUT:
|
||||
pull = FPIOA_PULL_NONE;
|
||||
dir = 0;
|
||||
break;
|
||||
case GPIO_DM_INPUT_PULL_DOWN:
|
||||
pull = FPIOA_PULL_DOWN;
|
||||
dir = 0;
|
||||
break;
|
||||
case GPIO_DM_INPUT_PULL_UP:
|
||||
pull = FPIOA_PULL_UP;
|
||||
dir = 0;
|
||||
break;
|
||||
case GPIO_DM_OUTPUT:
|
||||
pull = FPIOA_PULL_DOWN;
|
||||
dir = 1;
|
||||
break;
|
||||
default:
|
||||
configASSERT(!"GPIO drive mode is not supported.") break;
|
||||
}
|
||||
|
||||
fpioa_set_io_pull(io_number, pull);
|
||||
volatile uint32_t *reg = dir ? gpiohs->output_en.u32 : gpiohs->input_en.u32;
|
||||
volatile uint32_t *reg_d = !dir ? gpiohs->output_en.u32 : gpiohs->input_en.u32;
|
||||
set_gpio_bit(reg_d, pin, 0);
|
||||
set_gpio_bit(reg, pin, 1);
|
||||
}
|
||||
|
||||
gpio_pin_value_t gpiohs_get_pin(uint8_t pin)
|
||||
{
|
||||
configASSERT(pin < GPIOHS_MAX_PINNO);
|
||||
return get_gpio_bit(gpiohs->input_val.u32, pin);
|
||||
}
|
||||
|
||||
void gpiohs_set_pin(uint8_t pin, gpio_pin_value_t value)
|
||||
{
|
||||
configASSERT(pin < GPIOHS_MAX_PINNO);
|
||||
set_gpio_bit(gpiohs->output_val.u32, pin, value);
|
||||
}
|
||||
|
||||
void gpiohs_set_pin_edge(uint8_t pin, gpio_pin_edge_t edge)
|
||||
{
|
||||
set_gpio_bit(gpiohs->rise_ie.u32, pin, 0);
|
||||
set_gpio_bit(gpiohs->rise_ip.u32, pin, 1);
|
||||
|
||||
set_gpio_bit(gpiohs->fall_ie.u32, pin, 0);
|
||||
set_gpio_bit(gpiohs->fall_ip.u32, pin, 1);
|
||||
|
||||
set_gpio_bit(gpiohs->low_ie.u32, pin, 0);
|
||||
set_gpio_bit(gpiohs->low_ip.u32, pin, 1);
|
||||
|
||||
set_gpio_bit(gpiohs->high_ie.u32, pin, 0);
|
||||
set_gpio_bit(gpiohs->high_ip.u32, pin, 1);
|
||||
|
||||
if(edge & GPIO_PE_FALLING)
|
||||
{
|
||||
set_gpio_bit(gpiohs->fall_ie.u32, pin, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
set_gpio_bit(gpiohs->fall_ie.u32, pin, 0);
|
||||
}
|
||||
|
||||
if(edge & GPIO_PE_RISING)
|
||||
{
|
||||
set_gpio_bit(gpiohs->rise_ie.u32, pin, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
set_gpio_bit(gpiohs->rise_ie.u32, pin, 0);
|
||||
}
|
||||
|
||||
if(edge & GPIO_PE_LOW)
|
||||
{
|
||||
set_gpio_bit(gpiohs->low_ie.u32, pin, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
set_gpio_bit(gpiohs->low_ie.u32, pin, 0);
|
||||
}
|
||||
|
||||
if(edge & GPIO_PE_HIGH)
|
||||
{
|
||||
set_gpio_bit(gpiohs->high_ie.u32, pin, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
set_gpio_bit(gpiohs->high_ie.u32, pin, 0);
|
||||
}
|
||||
|
||||
pin_instance[pin].edge = edge;
|
||||
}
|
||||
|
||||
int gpiohs_pin_onchange_isr(void *userdata)
|
||||
{
|
||||
gpiohs_pin_instance_t *ctx = (gpiohs_pin_instance_t *)userdata;
|
||||
size_t pin = ctx->pin;
|
||||
|
||||
if(ctx->edge & GPIO_PE_FALLING)
|
||||
{
|
||||
set_gpio_bit(gpiohs->fall_ie.u32, pin, 0);
|
||||
set_gpio_bit(gpiohs->fall_ip.u32, pin, 1);
|
||||
set_gpio_bit(gpiohs->fall_ie.u32, pin, 1);
|
||||
}
|
||||
|
||||
if(ctx->edge & GPIO_PE_RISING)
|
||||
{
|
||||
set_gpio_bit(gpiohs->rise_ie.u32, pin, 0);
|
||||
set_gpio_bit(gpiohs->rise_ip.u32, pin, 1);
|
||||
set_gpio_bit(gpiohs->rise_ie.u32, pin, 1);
|
||||
}
|
||||
|
||||
if(ctx->edge & GPIO_PE_LOW)
|
||||
{
|
||||
set_gpio_bit(gpiohs->low_ie.u32, pin, 0);
|
||||
set_gpio_bit(gpiohs->low_ip.u32, pin, 1);
|
||||
set_gpio_bit(gpiohs->low_ie.u32, pin, 1);
|
||||
}
|
||||
|
||||
if(ctx->edge & GPIO_PE_HIGH)
|
||||
{
|
||||
set_gpio_bit(gpiohs->high_ie.u32, pin, 0);
|
||||
set_gpio_bit(gpiohs->high_ip.u32, pin, 1);
|
||||
set_gpio_bit(gpiohs->high_ie.u32, pin, 1);
|
||||
}
|
||||
|
||||
if (ctx->callback)
|
||||
ctx->callback();
|
||||
if(ctx->gpiohs_callback)
|
||||
ctx->gpiohs_callback(ctx->context);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void gpiohs_set_irq(uint8_t pin, uint32_t priority, void (*func)())
|
||||
{
|
||||
|
||||
pin_instance[pin].pin = pin;
|
||||
pin_instance[pin].callback = func;
|
||||
|
||||
plic_set_priority(IRQN_GPIOHS0_INTERRUPT + pin, priority);
|
||||
plic_irq_register(IRQN_GPIOHS0_INTERRUPT + pin, gpiohs_pin_onchange_isr, &(pin_instance[pin]));
|
||||
plic_irq_enable(IRQN_GPIOHS0_INTERRUPT + pin);
|
||||
}
|
||||
|
||||
void gpiohs_irq_register(uint8_t pin, uint32_t priority, plic_irq_callback_t callback, void *ctx)
|
||||
{
|
||||
pin_instance[pin].pin = pin;
|
||||
pin_instance[pin].gpiohs_callback = callback;
|
||||
pin_instance[pin].context = ctx;
|
||||
|
||||
plic_set_priority(IRQN_GPIOHS0_INTERRUPT + pin, priority);
|
||||
plic_irq_register(IRQN_GPIOHS0_INTERRUPT + pin, gpiohs_pin_onchange_isr, &(pin_instance[pin]));
|
||||
plic_irq_enable(IRQN_GPIOHS0_INTERRUPT + pin);
|
||||
}
|
||||
|
||||
void gpiohs_irq_unregister(uint8_t pin)
|
||||
{
|
||||
pin_instance[pin] = (gpiohs_pin_instance_t){
|
||||
.callback = NULL,
|
||||
.gpiohs_callback = NULL,
|
||||
.context = NULL,
|
||||
};
|
||||
set_gpio_bit(gpiohs->rise_ie.u32, pin, 0);
|
||||
set_gpio_bit(gpiohs->fall_ie.u32, pin, 0);
|
||||
set_gpio_bit(gpiohs->low_ie.u32, pin, 0);
|
||||
set_gpio_bit(gpiohs->high_ie.u32, pin, 0);
|
||||
plic_irq_unregister(IRQN_GPIOHS0_INTERRUPT + pin);
|
||||
}
|
||||
|
||||
void gpiohs_irq_disable(size_t pin)
|
||||
{
|
||||
plic_irq_disable(IRQN_GPIOHS0_INTERRUPT + pin);
|
||||
}
|
||||
|
||||
@@ -1,251 +0,0 @@
|
||||
/* Copyright 2018 Canaan Inc.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* http://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.
|
||||
*/
|
||||
#include <stddef.h>
|
||||
#include "i2c.h"
|
||||
#include "utils.h"
|
||||
#include "fpioa.h"
|
||||
#include "platform.h"
|
||||
#include "stdlib.h"
|
||||
#include "string.h"
|
||||
#include "sysctl.h"
|
||||
|
||||
typedef struct _i2c_slave_instance
|
||||
{
|
||||
uint32_t i2c_num;
|
||||
const i2c_slave_handler_t *slave_handler;
|
||||
} i2c_slave_instance_t;
|
||||
|
||||
static i2c_slave_instance_t slave_instance[I2C_MAX_NUM];
|
||||
|
||||
volatile i2c_t* const i2c[3] =
|
||||
{
|
||||
(volatile i2c_t*)I2C0_BASE_ADDR,
|
||||
(volatile i2c_t*)I2C1_BASE_ADDR,
|
||||
(volatile i2c_t*)I2C2_BASE_ADDR
|
||||
};
|
||||
|
||||
static void i2c_clk_init(i2c_device_number_t i2c_num)
|
||||
{
|
||||
configASSERT(i2c_num < I2C_MAX_NUM);
|
||||
sysctl_clock_enable(SYSCTL_CLOCK_I2C0 + i2c_num);
|
||||
sysctl_clock_set_threshold(SYSCTL_THRESHOLD_I2C0 + i2c_num, 3);
|
||||
}
|
||||
|
||||
void i2c_init(i2c_device_number_t i2c_num, uint32_t slave_address, uint32_t address_width,
|
||||
uint32_t i2c_clk)
|
||||
{
|
||||
configASSERT(i2c_num < I2C_MAX_NUM);
|
||||
configASSERT(address_width == 7 || address_width == 10);
|
||||
|
||||
volatile i2c_t *i2c_adapter = i2c[i2c_num];
|
||||
|
||||
i2c_clk_init(i2c_num);
|
||||
|
||||
uint32_t v_i2c_freq = sysctl_clock_get_freq(SYSCTL_CLOCK_I2C0 + i2c_num);
|
||||
uint16_t v_period_clk_cnt = v_i2c_freq / i2c_clk / 2;
|
||||
|
||||
if(v_period_clk_cnt == 0)
|
||||
v_period_clk_cnt = 1;
|
||||
|
||||
i2c_adapter->enable = 0;
|
||||
i2c_adapter->con = I2C_CON_MASTER_MODE | I2C_CON_SLAVE_DISABLE | I2C_CON_RESTART_EN |
|
||||
(address_width == 10 ? I2C_CON_10BITADDR_SLAVE : 0) | I2C_CON_SPEED(1);
|
||||
i2c_adapter->ss_scl_hcnt = I2C_SS_SCL_HCNT_COUNT(v_period_clk_cnt);
|
||||
i2c_adapter->ss_scl_lcnt = I2C_SS_SCL_LCNT_COUNT(v_period_clk_cnt);
|
||||
|
||||
i2c_adapter->tar = I2C_TAR_ADDRESS(slave_address);
|
||||
i2c_adapter->intr_mask = 0;
|
||||
i2c_adapter->dma_cr = 0x3;
|
||||
i2c_adapter->dma_rdlr = 0;
|
||||
i2c_adapter->dma_tdlr = 4;
|
||||
i2c_adapter->enable = I2C_ENABLE_ENABLE;
|
||||
}
|
||||
|
||||
static int i2c_slave_irq(void *userdata)
|
||||
{
|
||||
i2c_slave_instance_t *instance = (i2c_slave_instance_t *)userdata;
|
||||
volatile i2c_t *i2c_adapter = i2c[instance->i2c_num];
|
||||
uint32_t status = i2c_adapter->intr_stat;
|
||||
if (status & I2C_INTR_STAT_START_DET)
|
||||
{
|
||||
instance->slave_handler->on_event(I2C_EV_START);
|
||||
readl(&i2c_adapter->clr_start_det);
|
||||
}
|
||||
if (status & I2C_INTR_STAT_STOP_DET)
|
||||
{
|
||||
instance->slave_handler->on_event(I2C_EV_STOP);
|
||||
readl(&i2c_adapter->clr_stop_det);
|
||||
}
|
||||
if (status & I2C_INTR_STAT_RX_FULL)
|
||||
{
|
||||
instance->slave_handler->on_receive(i2c_adapter->data_cmd);
|
||||
}
|
||||
if (status & I2C_INTR_STAT_RD_REQ)
|
||||
{
|
||||
i2c_adapter->data_cmd = instance->slave_handler->on_transmit();
|
||||
readl(&i2c_adapter->clr_rd_req);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void i2c_init_as_slave(i2c_device_number_t i2c_num, uint32_t slave_address, uint32_t address_width,
|
||||
const i2c_slave_handler_t *handler)
|
||||
{
|
||||
configASSERT(address_width == 7 || address_width == 10);
|
||||
volatile i2c_t *i2c_adapter = i2c[i2c_num];
|
||||
slave_instance[i2c_num].i2c_num = i2c_num;
|
||||
slave_instance[i2c_num].slave_handler = handler;
|
||||
|
||||
i2c_clk_init(i2c_num);
|
||||
i2c_adapter->enable = 0;
|
||||
i2c_adapter->con = (address_width == 10 ? I2C_CON_10BITADDR_SLAVE : 0) | I2C_CON_SPEED(1) | I2C_CON_STOP_DET_IFADDRESSED;
|
||||
i2c_adapter->ss_scl_hcnt = I2C_SS_SCL_HCNT_COUNT(37);
|
||||
i2c_adapter->ss_scl_lcnt = I2C_SS_SCL_LCNT_COUNT(40);
|
||||
i2c_adapter->sar = I2C_SAR_ADDRESS(slave_address);
|
||||
i2c_adapter->rx_tl = I2C_RX_TL_VALUE(0);
|
||||
i2c_adapter->tx_tl = I2C_TX_TL_VALUE(0);
|
||||
i2c_adapter->intr_mask = I2C_INTR_MASK_RX_FULL | I2C_INTR_MASK_START_DET | I2C_INTR_MASK_STOP_DET | I2C_INTR_MASK_RD_REQ;
|
||||
|
||||
plic_set_priority(IRQN_I2C0_INTERRUPT + i2c_num, 1);
|
||||
plic_irq_register(IRQN_I2C0_INTERRUPT + i2c_num, i2c_slave_irq, slave_instance + i2c_num);
|
||||
plic_irq_enable(IRQN_I2C0_INTERRUPT + i2c_num);
|
||||
|
||||
i2c_adapter->enable = I2C_ENABLE_ENABLE;
|
||||
}
|
||||
|
||||
int i2c_send_data(i2c_device_number_t i2c_num, const uint8_t *send_buf, size_t send_buf_len)
|
||||
{
|
||||
configASSERT(i2c_num < I2C_MAX_NUM);
|
||||
volatile i2c_t* i2c_adapter = i2c[i2c_num];
|
||||
size_t fifo_len, index;
|
||||
i2c_adapter->clr_tx_abrt = i2c_adapter->clr_tx_abrt;
|
||||
while (send_buf_len)
|
||||
{
|
||||
fifo_len = 8 - i2c_adapter->txflr;
|
||||
fifo_len = send_buf_len < fifo_len ? send_buf_len : fifo_len;
|
||||
for (index = 0; index < fifo_len; index++)
|
||||
i2c_adapter->data_cmd = I2C_DATA_CMD_DATA(*send_buf++);
|
||||
if (i2c_adapter->tx_abrt_source != 0)
|
||||
return 1;
|
||||
send_buf_len -= fifo_len;
|
||||
}
|
||||
while ((i2c_adapter->status & I2C_STATUS_ACTIVITY) || !(i2c_adapter->status & I2C_STATUS_TFE))
|
||||
;
|
||||
|
||||
if (i2c_adapter->tx_abrt_source != 0)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void i2c_send_data_dma(dmac_channel_number_t dma_channel_num, i2c_device_number_t i2c_num, const uint8_t *send_buf,
|
||||
size_t send_buf_len)
|
||||
{
|
||||
configASSERT(i2c_num < I2C_MAX_NUM);
|
||||
volatile i2c_t* i2c_adapter = i2c[i2c_num];
|
||||
i2c_adapter->clr_tx_abrt = i2c_adapter->clr_tx_abrt;
|
||||
uint32_t *buf = malloc(send_buf_len * sizeof(uint32_t));
|
||||
int i;
|
||||
for (i = 0; i < send_buf_len; i++)
|
||||
{
|
||||
buf[i] = send_buf[i];
|
||||
}
|
||||
|
||||
sysctl_dma_select((sysctl_dma_channel_t)dma_channel_num, SYSCTL_DMA_SELECT_I2C0_TX_REQ + i2c_num * 2);
|
||||
dmac_set_single_mode(dma_channel_num, buf, (void *)(&i2c_adapter->data_cmd), DMAC_ADDR_INCREMENT, DMAC_ADDR_NOCHANGE,
|
||||
DMAC_MSIZE_4, DMAC_TRANS_WIDTH_32, send_buf_len);
|
||||
|
||||
dmac_wait_done(dma_channel_num);
|
||||
free((void *)buf);
|
||||
|
||||
while ((i2c_adapter->status & I2C_STATUS_ACTIVITY) || !(i2c_adapter->status & I2C_STATUS_TFE))
|
||||
{
|
||||
if (i2c_adapter->tx_abrt_source != 0)
|
||||
configASSERT(!"source abort");
|
||||
}
|
||||
}
|
||||
|
||||
int i2c_recv_data(i2c_device_number_t i2c_num, const uint8_t *send_buf, size_t send_buf_len, uint8_t *receive_buf,
|
||||
size_t receive_buf_len)
|
||||
{
|
||||
configASSERT(i2c_num < I2C_MAX_NUM);
|
||||
|
||||
size_t fifo_len, index;
|
||||
size_t rx_len = receive_buf_len;
|
||||
volatile i2c_t* i2c_adapter = i2c[i2c_num];
|
||||
|
||||
while (send_buf_len)
|
||||
{
|
||||
fifo_len = 8 - i2c_adapter->txflr;
|
||||
fifo_len = send_buf_len < fifo_len ? send_buf_len : fifo_len;
|
||||
for (index = 0; index < fifo_len; index++)
|
||||
i2c_adapter->data_cmd = I2C_DATA_CMD_DATA(*send_buf++);
|
||||
if (i2c_adapter->tx_abrt_source != 0)
|
||||
return 1;
|
||||
send_buf_len -= fifo_len;
|
||||
}
|
||||
|
||||
while (receive_buf_len || rx_len)
|
||||
{
|
||||
fifo_len = i2c_adapter->rxflr;
|
||||
fifo_len = rx_len < fifo_len ? rx_len : fifo_len;
|
||||
for (index = 0; index < fifo_len; index++)
|
||||
*receive_buf++ = (uint8_t)i2c_adapter->data_cmd;
|
||||
rx_len -= fifo_len;
|
||||
fifo_len = 8 - i2c_adapter->txflr;
|
||||
fifo_len = receive_buf_len < fifo_len ? receive_buf_len : fifo_len;
|
||||
for (index = 0; index < fifo_len; index++)
|
||||
i2c_adapter->data_cmd = I2C_DATA_CMD_CMD;
|
||||
if (i2c_adapter->tx_abrt_source != 0)
|
||||
return 1;
|
||||
receive_buf_len -= fifo_len;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void i2c_recv_data_dma(dmac_channel_number_t dma_send_channel_num, dmac_channel_number_t dma_receive_channel_num,
|
||||
i2c_device_number_t i2c_num, const uint8_t *send_buf, size_t send_buf_len,
|
||||
uint8_t *receive_buf, size_t receive_buf_len)
|
||||
{
|
||||
configASSERT(i2c_num < I2C_MAX_NUM);
|
||||
|
||||
volatile i2c_t* i2c_adapter = i2c[i2c_num];
|
||||
|
||||
uint32_t *write_cmd = malloc(sizeof(uint32_t) * (send_buf_len + receive_buf_len));
|
||||
size_t i;
|
||||
for(i = 0; i < send_buf_len; i++)
|
||||
write_cmd[i] = *send_buf++;
|
||||
for (i = 0; i < receive_buf_len; i++)
|
||||
write_cmd[i + send_buf_len] = I2C_DATA_CMD_CMD;
|
||||
|
||||
sysctl_dma_select((sysctl_dma_channel_t)dma_send_channel_num, SYSCTL_DMA_SELECT_I2C0_TX_REQ + i2c_num * 2);
|
||||
sysctl_dma_select((sysctl_dma_channel_t)dma_receive_channel_num, SYSCTL_DMA_SELECT_I2C0_RX_REQ + i2c_num * 2);
|
||||
|
||||
dmac_set_single_mode(dma_receive_channel_num, (void *)(&i2c_adapter->data_cmd), write_cmd, DMAC_ADDR_NOCHANGE,
|
||||
DMAC_ADDR_INCREMENT,DMAC_MSIZE_1, DMAC_TRANS_WIDTH_32, receive_buf_len);
|
||||
|
||||
dmac_set_single_mode(dma_send_channel_num, write_cmd, (void *)(&i2c_adapter->data_cmd), DMAC_ADDR_INCREMENT,
|
||||
DMAC_ADDR_NOCHANGE,DMAC_MSIZE_4, DMAC_TRANS_WIDTH_32, receive_buf_len + send_buf_len);
|
||||
|
||||
dmac_wait_done(dma_send_channel_num);
|
||||
dmac_wait_done(dma_receive_channel_num);
|
||||
|
||||
for (i = 0; i < receive_buf_len; i++)
|
||||
{
|
||||
receive_buf[i] = (uint8_t)write_cmd[i];
|
||||
}
|
||||
|
||||
free(write_cmd);
|
||||
}
|
||||
@@ -1,636 +0,0 @@
|
||||
/* Copyright 2018 Canaan Inc.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* http://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.
|
||||
*/
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
#include "i2s.h"
|
||||
#include "sysctl.h"
|
||||
#include "stdlib.h"
|
||||
#include "utils.h"
|
||||
|
||||
volatile i2s_t *const i2s[3] =
|
||||
{
|
||||
(volatile i2s_t *)I2S0_BASE_ADDR,
|
||||
(volatile i2s_t *)I2S1_BASE_ADDR,
|
||||
(volatile i2s_t *)I2S2_BASE_ADDR
|
||||
};
|
||||
|
||||
static int i2s_recv_channel_enable(i2s_device_number_t device_num,
|
||||
i2s_channel_num_t channel_num, uint32_t enable)
|
||||
{
|
||||
rer_t u_rer;
|
||||
|
||||
if (channel_num < I2S_CHANNEL_0 || channel_num > I2S_CHANNEL_3)
|
||||
return -1;
|
||||
u_rer.reg_data = readl(&i2s[device_num]->channel[channel_num].rer);
|
||||
u_rer.rer.rxchenx = enable;
|
||||
writel(u_rer.reg_data, &i2s[device_num]->channel[channel_num].rer);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int i2s_transmit_channel_enable(i2s_device_number_t device_num,
|
||||
i2s_channel_num_t channel_num, uint32_t enable)
|
||||
{
|
||||
ter_t u_ter;
|
||||
|
||||
if (channel_num < I2S_CHANNEL_0 || channel_num > I2S_CHANNEL_3)
|
||||
return -1;
|
||||
|
||||
u_ter.reg_data = readl(&i2s[device_num]->channel[channel_num].ter);
|
||||
u_ter.ter.txchenx = enable;
|
||||
writel(u_ter.reg_data, &i2s[device_num]->channel[channel_num].ter);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void i2s_receive_enable(i2s_device_number_t device_num, i2s_channel_num_t channel_num)
|
||||
{
|
||||
irer_t u_irer;
|
||||
|
||||
u_irer.reg_data = readl(&i2s[device_num]->irer);
|
||||
u_irer.irer.rxen = 1;
|
||||
writel(u_irer.reg_data, &i2s[device_num]->irer);
|
||||
/* Receiver block enable */
|
||||
|
||||
i2s_recv_channel_enable(device_num, channel_num, 1);
|
||||
/* Receive channel enable */
|
||||
}
|
||||
|
||||
static void i2s_transimit_enable(i2s_device_number_t device_num, i2s_channel_num_t channel_num)
|
||||
{
|
||||
iter_t u_iter;
|
||||
|
||||
u_iter.reg_data = readl(&i2s[device_num]->iter);
|
||||
u_iter.iter.txen = 1;
|
||||
writel(u_iter.reg_data, &i2s[device_num]->iter);
|
||||
/* Transmitter block enable */
|
||||
|
||||
i2s_transmit_channel_enable(device_num, channel_num, 1);
|
||||
/* Transmit channel enable */
|
||||
}
|
||||
|
||||
static void i2s_set_enable(i2s_device_number_t device_num, uint32_t enable)
|
||||
{
|
||||
ier_t u_ier;
|
||||
|
||||
u_ier.reg_data = readl(&i2s[device_num]->ier);
|
||||
u_ier.ier.ien = enable;
|
||||
writel(u_ier.reg_data, &i2s[device_num]->ier);
|
||||
}
|
||||
|
||||
static void i2s_disable_block(i2s_device_number_t device_num, i2s_transmit_t rxtx_mode)
|
||||
{
|
||||
irer_t u_irer;
|
||||
iter_t u_iter;
|
||||
|
||||
if (rxtx_mode == I2S_RECEIVER)
|
||||
{
|
||||
u_irer.reg_data = readl(&i2s[device_num]->irer);
|
||||
u_irer.irer.rxen = 0;
|
||||
writel(u_irer.reg_data, &i2s[device_num]->irer);
|
||||
/* Receiver block disable */
|
||||
}
|
||||
else
|
||||
{
|
||||
u_iter.reg_data = readl(&i2s[device_num]->iter);
|
||||
u_iter.iter.txen = 0;
|
||||
writel(u_iter.reg_data, &i2s[device_num]->iter);
|
||||
/* Transmitter block disable */
|
||||
}
|
||||
}
|
||||
|
||||
static int i2s_set_rx_word_length(i2s_device_number_t device_num,
|
||||
i2s_word_length_t word_length,
|
||||
i2s_channel_num_t channel_num)
|
||||
{
|
||||
rcr_tcr_t u_rcr;
|
||||
|
||||
if (word_length > RESOLUTION_32_BIT || word_length < IGNORE_WORD_LENGTH)
|
||||
return -1;
|
||||
if (channel_num < I2S_CHANNEL_0 || channel_num > I2S_CHANNEL_3)
|
||||
return -1;
|
||||
|
||||
u_rcr.reg_data = readl(&i2s[device_num]->channel[channel_num].rcr);
|
||||
u_rcr.rcr_tcr.wlen = word_length;
|
||||
writel(u_rcr.reg_data, &i2s[device_num]->channel[channel_num].rcr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int i2s_set_tx_word_length(i2s_device_number_t device_num,
|
||||
i2s_word_length_t word_length,
|
||||
i2s_channel_num_t channel_num)
|
||||
{
|
||||
rcr_tcr_t u_tcr;
|
||||
|
||||
if (word_length > RESOLUTION_32_BIT || word_length < IGNORE_WORD_LENGTH)
|
||||
return -1;
|
||||
if (channel_num < I2S_CHANNEL_0 || channel_num > I2S_CHANNEL_3)
|
||||
return -1;
|
||||
|
||||
u_tcr.reg_data = readl(&i2s[device_num]->channel[channel_num].tcr);
|
||||
u_tcr.rcr_tcr.wlen = word_length;
|
||||
writel(u_tcr.reg_data, &i2s[device_num]->channel[channel_num].tcr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void i2s_master_configure(i2s_device_number_t device_num,
|
||||
i2s_word_select_cycles_t word_select_size,
|
||||
i2s_sclk_gating_cycles_t gating_cycles,
|
||||
i2s_work_mode_t word_mode)
|
||||
{
|
||||
configASSERT(!(word_select_size < SCLK_CYCLES_16 ||
|
||||
word_select_size > SCLK_CYCLES_32));
|
||||
configASSERT(!(gating_cycles < NO_CLOCK_GATING ||
|
||||
gating_cycles > CLOCK_CYCLES_24));
|
||||
|
||||
ccr_t u_ccr;
|
||||
cer_t u_cer;
|
||||
|
||||
u_ccr.reg_data = readl(&i2s[device_num]->ccr);
|
||||
u_ccr.ccr.clk_word_size = word_select_size;
|
||||
u_ccr.ccr.clk_gate = gating_cycles;
|
||||
u_ccr.ccr.align_mode = word_mode;
|
||||
writel(u_ccr.reg_data, &i2s[device_num]->ccr);
|
||||
|
||||
u_cer.reg_data = readl(&i2s[device_num]->cer);
|
||||
u_cer.cer.clken = 1;
|
||||
writel(u_cer.reg_data, &i2s[device_num]->cer);
|
||||
/* Clock generation enable */
|
||||
|
||||
}
|
||||
|
||||
static int i2s_set_rx_threshold(i2s_device_number_t device_num,
|
||||
i2s_fifo_threshold_t threshold,
|
||||
i2s_channel_num_t channel_num)
|
||||
{
|
||||
rfcr_t u_rfcr;
|
||||
|
||||
if (threshold < TRIGGER_LEVEL_1 || threshold > TRIGGER_LEVEL_16)
|
||||
return -1;
|
||||
if (channel_num < I2S_CHANNEL_0 || channel_num > I2S_CHANNEL_3)
|
||||
return -1;
|
||||
|
||||
u_rfcr.reg_data = readl(&i2s[device_num]->channel[channel_num].rfcr);
|
||||
u_rfcr.rfcr.rxchdt = threshold;
|
||||
writel(u_rfcr.reg_data, &i2s[device_num]->channel[channel_num].rfcr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int i2s_set_tx_threshold(i2s_device_number_t device_num,
|
||||
i2s_fifo_threshold_t threshold,
|
||||
i2s_channel_num_t channel_num)
|
||||
{
|
||||
tfcr_t u_tfcr;
|
||||
|
||||
if (threshold < TRIGGER_LEVEL_1 || threshold > TRIGGER_LEVEL_16)
|
||||
return -1;
|
||||
if (channel_num < I2S_CHANNEL_0 || channel_num > I2S_CHANNEL_3)
|
||||
return -1;
|
||||
|
||||
u_tfcr.reg_data = readl(&i2s[device_num]->channel[channel_num].tfcr);
|
||||
u_tfcr.tfcr.txchet = threshold;
|
||||
writel(u_tfcr.reg_data, &i2s[device_num]->channel[channel_num].tfcr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int i2s_set_mask_interrupt(i2s_device_number_t device_num,
|
||||
i2s_channel_num_t channel_num,
|
||||
uint32_t rx_available_int, uint32_t rx_overrun_int,
|
||||
uint32_t tx_empty_int, uint32_t tx_overrun_int)
|
||||
{
|
||||
imr_t u_imr;
|
||||
|
||||
if (channel_num < I2S_CHANNEL_0 || channel_num > I2S_CHANNEL_3)
|
||||
return -1;
|
||||
u_imr.reg_data = readl(&i2s[device_num]->channel[channel_num].imr);
|
||||
|
||||
if (rx_available_int == 1)
|
||||
u_imr.imr.rxdam = 1;
|
||||
else
|
||||
u_imr.imr.rxdam = 0;
|
||||
if (rx_overrun_int == 1)
|
||||
u_imr.imr.rxfom = 1;
|
||||
else
|
||||
u_imr.imr.rxfom = 0;
|
||||
|
||||
if (tx_empty_int == 1)
|
||||
u_imr.imr.txfem = 1;
|
||||
else
|
||||
u_imr.imr.txfem = 0;
|
||||
if (tx_overrun_int == 1)
|
||||
u_imr.imr.txfom = 1;
|
||||
else
|
||||
u_imr.imr.txfom = 0;
|
||||
writel(u_imr.reg_data, &i2s[device_num]->channel[channel_num].imr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int i2s_transmit_dma_enable(i2s_device_number_t device_num, uint32_t enable)
|
||||
{
|
||||
ccr_t u_ccr;
|
||||
|
||||
if (device_num >= I2S_DEVICE_MAX)
|
||||
return -1;
|
||||
|
||||
u_ccr.reg_data = readl(&i2s[device_num]->ccr);
|
||||
u_ccr.ccr.dma_tx_en = enable;
|
||||
writel(u_ccr.reg_data, &i2s[device_num]->ccr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int i2s_receive_dma_enable(i2s_device_number_t device_num, uint32_t enable)
|
||||
{
|
||||
ccr_t u_ccr;
|
||||
|
||||
if (device_num >= I2S_DEVICE_MAX)
|
||||
return -1;
|
||||
|
||||
u_ccr.reg_data = readl(&i2s[device_num]->ccr);
|
||||
u_ccr.ccr.dma_rx_en = enable;
|
||||
writel(u_ccr.reg_data, &i2s[device_num]->ccr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int i2s_set_dma_divide_16(i2s_device_number_t device_num, uint32_t enable)
|
||||
{
|
||||
ccr_t u_ccr;
|
||||
|
||||
if (device_num >= I2S_DEVICE_MAX)
|
||||
return -1;
|
||||
|
||||
u_ccr.reg_data = readl(&i2s[device_num]->ccr);
|
||||
u_ccr.ccr.dma_divide_16 = enable;
|
||||
writel(u_ccr.reg_data, &i2s[device_num]->ccr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int i2s_get_dma_divide_16(i2s_device_number_t device_num)
|
||||
{
|
||||
if (device_num >= I2S_DEVICE_MAX)
|
||||
return -1;
|
||||
ccr_t u_ccr;
|
||||
u_ccr.reg_data = readl(&i2s[device_num]->ccr);
|
||||
return u_ccr.ccr.dma_divide_16;
|
||||
}
|
||||
|
||||
int i2s_receive_data(i2s_device_number_t device_num, i2s_channel_num_t channel_num, uint64_t *buf, size_t buf_len)
|
||||
{
|
||||
uint32_t i = 0;
|
||||
isr_t u_isr;
|
||||
|
||||
readl(&i2s[device_num]->channel[channel_num].ror);
|
||||
/*clear over run*/
|
||||
|
||||
for (i = 0; i < buf_len;)
|
||||
{
|
||||
u_isr.reg_data = readl(&i2s[device_num]->channel[channel_num].isr);
|
||||
if (u_isr.isr.rxda == 1)
|
||||
{
|
||||
buf[i] = readl(&i2s[device_num]->channel[channel_num].left_rxtx);
|
||||
buf[i] <<= 32;
|
||||
buf[i++] |= readl(&i2s[device_num]->channel[channel_num].right_rxtx);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void i2s_receive_data_dma(i2s_device_number_t device_num, uint32_t *buf,
|
||||
size_t buf_len, dmac_channel_number_t channel_num)
|
||||
{
|
||||
dmac_wait_idle(channel_num);
|
||||
sysctl_dma_select((sysctl_dma_channel_t)channel_num, SYSCTL_DMA_SELECT_I2S0_RX_REQ + device_num * 2);
|
||||
dmac_set_single_mode(channel_num, (void *)(&i2s[device_num]->rxdma), buf, DMAC_ADDR_NOCHANGE, DMAC_ADDR_INCREMENT,
|
||||
DMAC_MSIZE_1, DMAC_TRANS_WIDTH_32, buf_len);
|
||||
}
|
||||
|
||||
int i2s_rx_to_tx(i2s_device_number_t device_src_num, i2s_device_number_t device_dest_num,
|
||||
size_t buf_len, dmac_channel_number_t channel_num)
|
||||
{
|
||||
static uint8_t dmac_recv_flag[6] = {0,0,0,0,0,0};
|
||||
if(dmac_recv_flag[channel_num])
|
||||
dmac_wait_done(channel_num);
|
||||
else
|
||||
dmac_recv_flag[channel_num] = 1;
|
||||
sysctl_dma_select((sysctl_dma_channel_t)channel_num, SYSCTL_DMA_SELECT_I2S0_RX_REQ + device_src_num * 2);
|
||||
dmac_set_single_mode(channel_num, (void *)(&i2s[device_src_num]->rxdma), (void *)(&i2s[device_dest_num]->txdma), DMAC_ADDR_NOCHANGE, DMAC_ADDR_NOCHANGE,
|
||||
DMAC_MSIZE_1, DMAC_TRANS_WIDTH_32, buf_len);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int i2s_send_data(i2s_device_number_t device_num, i2s_channel_num_t channel_num, const uint8_t *pcm, size_t buf_len,
|
||||
size_t single_length)
|
||||
{
|
||||
isr_t u_isr;
|
||||
uint32_t left_buffer = 0;
|
||||
uint32_t right_buffer = 0;
|
||||
uint32_t i = 0;
|
||||
uint32_t j = 0;
|
||||
if (channel_num < I2S_CHANNEL_0 || channel_num > I2S_CHANNEL_3)
|
||||
return -1;
|
||||
|
||||
buf_len = buf_len / (single_length / 8) / 2; /* sample num */
|
||||
readl(&i2s[device_num]->channel[channel_num].tor);
|
||||
/* read clear overrun flag */
|
||||
|
||||
for (j = 0; j < buf_len;)
|
||||
{
|
||||
u_isr.reg_data = readl(&i2s[device_num]->channel[channel_num].isr);
|
||||
if (u_isr.isr.txfe == 1)
|
||||
{
|
||||
switch(single_length)
|
||||
{
|
||||
case 16:
|
||||
left_buffer = ((uint16_t *)pcm)[i++];
|
||||
right_buffer = ((uint16_t *)pcm)[i++];
|
||||
break;
|
||||
case 24:
|
||||
left_buffer = 0;
|
||||
left_buffer |= pcm[i++];
|
||||
left_buffer |= pcm[i++] << 8;
|
||||
left_buffer |= pcm[i++] << 16;
|
||||
right_buffer = 0;
|
||||
right_buffer |= pcm[i++];
|
||||
right_buffer |= pcm[i++] << 8;
|
||||
right_buffer |= pcm[i++] << 16;
|
||||
break;
|
||||
case 32:
|
||||
left_buffer = ((uint32_t *)pcm)[i++];
|
||||
right_buffer = ((uint32_t *)pcm)[i++];
|
||||
break;
|
||||
default:
|
||||
left_buffer = pcm[i++];
|
||||
right_buffer = pcm[i++];
|
||||
break;
|
||||
}
|
||||
writel(left_buffer, &i2s[device_num]->channel[channel_num].left_rxtx);
|
||||
writel(right_buffer, &i2s[device_num]->channel[channel_num].right_rxtx);
|
||||
j++;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void i2s_send_data_dma(i2s_device_number_t device_num, const void *buf, size_t buf_len, dmac_channel_number_t channel_num)
|
||||
{
|
||||
|
||||
dmac_wait_idle(channel_num);
|
||||
sysctl_dma_select((sysctl_dma_channel_t)channel_num, SYSCTL_DMA_SELECT_I2S0_TX_REQ + device_num * 2);
|
||||
dmac_set_single_mode(channel_num, buf, (void *)(&i2s[device_num]->txdma), DMAC_ADDR_INCREMENT,
|
||||
DMAC_ADDR_NOCHANGE, DMAC_MSIZE_1, DMAC_TRANS_WIDTH_32, buf_len);
|
||||
}
|
||||
|
||||
static void i2s_parse_voice(i2s_device_number_t device_num, uint32_t *buf, const uint8_t *pcm, size_t length, size_t bits_per_sample,
|
||||
uint8_t track_num, size_t *send_len)
|
||||
{
|
||||
uint32_t i,j=0;
|
||||
*send_len = length * 2;
|
||||
switch(bits_per_sample)
|
||||
{
|
||||
case 16:
|
||||
for(i = 0; i < length; i++)
|
||||
{
|
||||
buf[2*i] = ((uint16_t *)pcm)[i];
|
||||
buf[2*i+1] = 0;
|
||||
}
|
||||
break;
|
||||
case 24:
|
||||
for(i = 0; i < length; i++)
|
||||
{
|
||||
buf[2*i] = 0;
|
||||
buf[2*i] |= pcm[j++];
|
||||
buf[2*i] |= pcm[j++] << 8;
|
||||
buf[2*i] |= pcm[j++] << 16;
|
||||
buf[2*i+1] = 0;
|
||||
if(track_num == 2)
|
||||
{
|
||||
buf[2*i+1] |= pcm[j++];
|
||||
buf[2*i+1] |= pcm[j++] << 8;
|
||||
buf[2*i+1] |= pcm[j++] << 16;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 32:
|
||||
default:
|
||||
for(i = 0; i < length; i++)
|
||||
{
|
||||
buf[2*i] = ((uint32_t *)pcm)[i];
|
||||
buf[2*i+1] = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void i2s_play(i2s_device_number_t device_num, dmac_channel_number_t channel_num,
|
||||
const uint8_t *buf, size_t buf_len, size_t frame, size_t bits_per_sample, uint8_t track_num)
|
||||
{
|
||||
const uint8_t *trans_buf;
|
||||
uint32_t i;
|
||||
size_t sample_cnt = buf_len / ( bits_per_sample / 8 ) / track_num;
|
||||
size_t frame_cnt = sample_cnt / frame;
|
||||
size_t frame_remain = sample_cnt % frame;
|
||||
i2s_set_dma_divide_16(device_num, 0);
|
||||
|
||||
if (bits_per_sample == 16 && track_num == 2)
|
||||
{
|
||||
i2s_set_dma_divide_16(device_num, 1);
|
||||
for (i = 0; i < frame_cnt; i++)
|
||||
{
|
||||
trans_buf = buf + i * frame * (bits_per_sample / 8) * track_num;
|
||||
i2s_send_data_dma(device_num,trans_buf, frame, channel_num);
|
||||
}
|
||||
if(frame_remain)
|
||||
{
|
||||
trans_buf = buf + frame_cnt * frame * (bits_per_sample / 8) * track_num;
|
||||
i2s_send_data_dma(device_num, trans_buf, frame_remain, channel_num);
|
||||
}
|
||||
}
|
||||
else if (bits_per_sample == 32 && track_num == 2)
|
||||
{
|
||||
for (i = 0; i < frame_cnt; i++)
|
||||
{
|
||||
trans_buf = buf + i * frame * (bits_per_sample / 8) * track_num;
|
||||
i2s_send_data_dma(device_num,trans_buf, frame * 2, channel_num);
|
||||
}
|
||||
if(frame_remain)
|
||||
{
|
||||
trans_buf = buf + frame_cnt * frame * (bits_per_sample / 8) * track_num;
|
||||
i2s_send_data_dma(device_num, trans_buf, frame_remain * 2, channel_num);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
uint32_t *buff[2];
|
||||
buff[0] = malloc(frame * 2 * sizeof(uint32_t) * 2);
|
||||
buff[1] = buff[0] + frame * 2;
|
||||
uint8_t flag = 0;
|
||||
size_t send_len = 0;
|
||||
for (i = 0; i < frame_cnt; i++)
|
||||
{
|
||||
trans_buf = buf + i * frame * (bits_per_sample / 8) * track_num;
|
||||
i2s_parse_voice(device_num, buff[flag], trans_buf, frame, bits_per_sample, track_num, &send_len);
|
||||
i2s_send_data_dma(device_num,buff[flag], send_len, channel_num);
|
||||
flag = !flag;
|
||||
}
|
||||
if (frame_remain)
|
||||
{
|
||||
trans_buf = buf + frame_cnt * frame * (bits_per_sample / 8) * track_num;
|
||||
i2s_parse_voice(device_num, buff[flag], trans_buf, frame_remain, bits_per_sample, track_num, &send_len);
|
||||
i2s_send_data_dma(device_num, trans_buf, send_len, channel_num);
|
||||
}
|
||||
free(buff[0]);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void i2s_set_sign_expand_en(i2s_device_number_t device_num, uint32_t enable)
|
||||
{
|
||||
ccr_t u_ccr;
|
||||
u_ccr.reg_data = readl(&i2s[device_num]->ccr);
|
||||
u_ccr.ccr.sign_expand_en = enable;
|
||||
writel(u_ccr.reg_data, &i2s[device_num]->ccr);
|
||||
}
|
||||
|
||||
void i2s_rx_channel_config(i2s_device_number_t device_num,
|
||||
i2s_channel_num_t channel_num,
|
||||
i2s_word_length_t word_length,
|
||||
i2s_word_select_cycles_t word_select_size,
|
||||
i2s_fifo_threshold_t trigger_level,
|
||||
i2s_work_mode_t word_mode)
|
||||
{
|
||||
i2s_recv_channel_enable(device_num, channel_num, 0);
|
||||
/* Receive channel disable */
|
||||
|
||||
writel(0, &i2s[device_num]->channel[channel_num].ter);
|
||||
/* disable tx */
|
||||
|
||||
writel(1, &i2s[device_num]->channel[channel_num].rff);
|
||||
/* flash individual fifo */
|
||||
|
||||
writel(1, &i2s[device_num]->rxffr);
|
||||
/* flush tx fifo*/
|
||||
|
||||
i2s_set_rx_word_length(device_num, word_length, channel_num);
|
||||
/* Word buf_len is RESOLUTION_32_BIT */
|
||||
|
||||
i2s_master_configure(device_num,
|
||||
word_select_size, NO_CLOCK_GATING, word_mode);
|
||||
/* word select size is 32 bits,no clock gating */
|
||||
|
||||
i2s_set_rx_threshold(device_num, trigger_level, channel_num);
|
||||
/* Interrupt trigger when FIFO level is 8 */
|
||||
|
||||
readl(&i2s[device_num]->channel[channel_num].ror);
|
||||
readl(&i2s[device_num]->channel[channel_num].tor);
|
||||
|
||||
i2s_recv_channel_enable(device_num, channel_num, 1);
|
||||
}
|
||||
|
||||
void i2s_tx_channel_config(i2s_device_number_t device_num,
|
||||
i2s_channel_num_t channel_num,
|
||||
i2s_word_length_t word_length,
|
||||
i2s_word_select_cycles_t word_select_size,
|
||||
i2s_fifo_threshold_t trigger_level,
|
||||
i2s_work_mode_t word_mode)
|
||||
{
|
||||
writel(0, &i2s[device_num]->channel[channel_num].rer);
|
||||
/* disable rx */
|
||||
|
||||
i2s_transmit_channel_enable(device_num, channel_num, 0);
|
||||
/* Transmit channel disable */
|
||||
|
||||
writel(1, &i2s[device_num]->txffr);
|
||||
/* flush tx fifo */
|
||||
writel(1, &i2s[device_num]->channel[channel_num].tff);
|
||||
/* flush individual fifo */
|
||||
|
||||
i2s_set_tx_word_length(device_num, word_length, channel_num);
|
||||
/* Word buf_len is RESOLUTION_16_BIT */
|
||||
|
||||
i2s_master_configure(device_num, word_select_size, NO_CLOCK_GATING, word_mode);
|
||||
/* word select size is 16 bits,gating after 16 bit */
|
||||
|
||||
i2s_set_tx_threshold(device_num, trigger_level, channel_num);
|
||||
/* Interrupt trigger when FIFO level is 8 */
|
||||
|
||||
i2s_transmit_channel_enable(device_num, channel_num, 1);
|
||||
}
|
||||
|
||||
|
||||
void i2s_init(i2s_device_number_t device_num, i2s_transmit_t rxtx_mode, uint32_t channel_mask)
|
||||
{
|
||||
sysctl_clock_enable(SYSCTL_CLOCK_I2S0 + device_num);
|
||||
sysctl_reset(SYSCTL_RESET_I2S0 + device_num);
|
||||
sysctl_clock_set_threshold(SYSCTL_THRESHOLD_I2S0 + device_num, 7);
|
||||
/*96k:5,44k:12,24k:23,22k:25 16k:35 sampling*/
|
||||
/*sample rate*32bit*2 =75MHz/((N+1)*2) */
|
||||
i2s_set_enable(device_num, 1);
|
||||
i2s_disable_block(device_num, I2S_TRANSMITTER);
|
||||
i2s_disable_block(device_num, I2S_RECEIVER);
|
||||
|
||||
if (rxtx_mode == I2S_TRANSMITTER)
|
||||
{
|
||||
for (int i=0; i<4; i++)
|
||||
{
|
||||
if ((channel_mask & 0x3) == 0x3)
|
||||
{
|
||||
i2s_set_mask_interrupt(device_num, I2S_CHANNEL_0 + i, 1, 1, 1, 1);
|
||||
i2s_transimit_enable(device_num, I2S_CHANNEL_0 + i);
|
||||
}
|
||||
else
|
||||
{
|
||||
i2s_transmit_channel_enable(device_num, I2S_CHANNEL_0 + i, 0);
|
||||
}
|
||||
channel_mask >>= 2;
|
||||
}
|
||||
i2s_transmit_dma_enable(device_num, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i=0; i<4; i++)
|
||||
{
|
||||
if ((channel_mask & 0x3) == 0x3)
|
||||
{
|
||||
i2s_set_mask_interrupt(device_num, I2S_CHANNEL_0 + i, 1, 1, 1, 1);
|
||||
i2s_receive_enable(device_num, I2S_CHANNEL_0 + i);
|
||||
}
|
||||
else
|
||||
{
|
||||
i2s_recv_channel_enable(device_num, I2S_CHANNEL_0 + i, 0);
|
||||
}
|
||||
channel_mask >>= 2;
|
||||
}
|
||||
/* Set expand_en when receive */
|
||||
i2s_set_sign_expand_en(device_num, 1);
|
||||
i2s_receive_dma_enable(device_num, 1);
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t i2s_set_sample_rate(i2s_device_number_t device_num, uint32_t sample_rate)
|
||||
{
|
||||
ccr_t u_ccr;
|
||||
uint32_t pll2_clock = 0;
|
||||
pll2_clock = sysctl_pll_get_freq(SYSCTL_PLL2);
|
||||
|
||||
u_ccr.reg_data = readl(&i2s[device_num]->ccr);
|
||||
/* 0x0 for 16sclk cycles, 0x1 for 24 sclk cycles 0x2 for 32 sclk */
|
||||
uint32_t v_clk_word_size = (u_ccr.ccr.clk_word_size + 2) * 8;
|
||||
uint32_t threshold = round(pll2_clock / (sample_rate * 2.0 * v_clk_word_size * 2.0) - 1);
|
||||
sysctl_clock_set_threshold(SYSCTL_THRESHOLD_I2S0 + device_num, threshold);
|
||||
return sysctl_clock_get_freq(SYSCTL_CLOCK_I2S0 + device_num);
|
||||
}
|
||||
|
||||
@@ -1,767 +0,0 @@
|
||||
/* Copyright 2018 Canaan Inc.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* http://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 _DRIVER_AES_H
|
||||
#define _DRIVER_AES_H
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include "platform.h"
|
||||
#include "dmac.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef enum _aes_cipher_mode
|
||||
{
|
||||
AES_ECB = 0,
|
||||
AES_CBC = 1,
|
||||
AES_GCM = 2,
|
||||
AES_CIPHER_MAX,
|
||||
} aes_cipher_mode_t;
|
||||
|
||||
typedef enum _aes_kmode
|
||||
{
|
||||
AES_128 = 16,
|
||||
AES_192 = 24,
|
||||
AES_256 = 32,
|
||||
} aes_kmode_t;
|
||||
|
||||
typedef enum _aes_iv_len
|
||||
{
|
||||
IV_LEN_96 = 12,
|
||||
IV_LEN_128 = 16,
|
||||
} aes_iv_len_t;
|
||||
|
||||
typedef enum _aes_encrypt_sel
|
||||
{
|
||||
AES_HARD_ENCRYPTION = 0,
|
||||
AES_HARD_DECRYPTION = 1,
|
||||
} aes_encrypt_sel_t;
|
||||
|
||||
typedef struct _aes_mode_ctl
|
||||
{
|
||||
/* [2:0]:000:ecb; 001:cbc,010:gcm */
|
||||
uint32_t cipher_mode : 3;
|
||||
/* [4:3]:00:aes-128; 01:aes-192; 10:aes-256;11:reserved*/
|
||||
uint32_t kmode : 2;
|
||||
/* [6:5]:input key order 1:little endian; 0: big endian */
|
||||
uint32_t key_order : 2;
|
||||
/* [8:7]:input data order 1:little endian; 0: big endian */
|
||||
uint32_t input_order : 2;
|
||||
/* [10:9]:output data order 1:little endian; 0: big endian */
|
||||
uint32_t output_order : 2;
|
||||
uint32_t reserved : 21;
|
||||
} __attribute__((packed, aligned(4))) aes_mode_ctl_t;
|
||||
|
||||
/**
|
||||
* @brief AES
|
||||
*/
|
||||
typedef struct _aes
|
||||
{
|
||||
/* (0x00) customer key.1st~4th byte key */
|
||||
uint32_t aes_key[4];
|
||||
/* (0x10) 0: encryption; 1: decryption */
|
||||
uint32_t encrypt_sel;
|
||||
/* (0x14) aes mode reg */
|
||||
aes_mode_ctl_t mode_ctl;
|
||||
/* (0x18) Initialisation Vector. GCM support 96bit. CBC support 128bit */
|
||||
uint32_t aes_iv[4];
|
||||
/* (0x28) input data endian;1:little endian; 0:big endian */
|
||||
uint32_t aes_endian;
|
||||
/* (0x2c) calculate status. 1:finish; 0:not finish */
|
||||
uint32_t aes_finish;
|
||||
/* (0x30) aes out data to dma 0:cpu 1:dma */
|
||||
uint32_t dma_sel;
|
||||
/* (0x34) gcm Additional authenticated data number */
|
||||
uint32_t gb_aad_num;
|
||||
uint32_t reserved;
|
||||
/* (0x3c) aes plantext/ciphter text input data number */
|
||||
uint32_t gb_pc_num;
|
||||
/* (0x40) aes plantext/ciphter text input data */
|
||||
uint32_t aes_text_data;
|
||||
/* (0x44) Additional authenticated data */
|
||||
uint32_t aes_aad_data;
|
||||
/**
|
||||
* (0x48) [1:0],b'00:check not finish; b'01:check fail; b'10:check success;
|
||||
* b'11:reversed
|
||||
*/
|
||||
uint32_t tag_chk;
|
||||
/* (0x4c) data can input flag. 1: data can input; 0 : data cannot input */
|
||||
uint32_t data_in_flag;
|
||||
/* (0x50) gcm input tag for compare with the calculate tag */
|
||||
uint32_t gcm_in_tag[4];
|
||||
/* (0x60) aes plantext/ciphter text output data */
|
||||
uint32_t aes_out_data;
|
||||
/* (0x64) aes module enable */
|
||||
uint32_t gb_aes_en;
|
||||
/* (0x68) data can output flag 1: data ready 0: data not ready */
|
||||
uint32_t data_out_flag;
|
||||
/* (0x6c) allow tag input when use gcm */
|
||||
uint32_t tag_in_flag;
|
||||
/* (0x70) clear tag_chk */
|
||||
uint32_t tag_clear;
|
||||
uint32_t gcm_out_tag[4];
|
||||
/* (0x84) customer key for aes-192 aes-256.5th~8th byte key */
|
||||
uint32_t aes_key_ext[4];
|
||||
} __attribute__((packed, aligned(4))) aes_t;
|
||||
|
||||
typedef struct _gcm_context
|
||||
{
|
||||
/* The buffer holding the encryption or decryption key. */
|
||||
uint8_t *input_key;
|
||||
/* The initialization vector. must be 96 bit */
|
||||
uint8_t *iv;
|
||||
/* The buffer holding the Additional authenticated data. or NULL */
|
||||
uint8_t *gcm_aad;
|
||||
/* The length of the Additional authenticated data. or 0L */
|
||||
size_t gcm_aad_len;
|
||||
} gcm_context_t;
|
||||
|
||||
typedef struct _cbc_context
|
||||
{
|
||||
/* The buffer holding the encryption or decryption key. */
|
||||
uint8_t *input_key;
|
||||
/* The initialization vector. must be 128 bit */
|
||||
uint8_t *iv;
|
||||
} cbc_context_t;
|
||||
|
||||
/**
|
||||
* @brief AES-ECB-128 decryption
|
||||
*
|
||||
* @param[in] input_key The decryption key. must be 16bytes.
|
||||
* @param[in] input_data The buffer holding the input data.
|
||||
* @param[in] input_len The length of a data unit in bytes.
|
||||
* This can be any length between 16 bytes and 2^31 bytes inclusive
|
||||
* (between 1 and 2^27 block cipher blocks).
|
||||
* @param[out] output_data The buffer holding the output data.
|
||||
* The buffer size must be larger than the size after padding by 16 byte multiples.
|
||||
*/
|
||||
void aes_ecb128_hard_decrypt(uint8_t *input_key, uint8_t *input_data, size_t input_len, uint8_t *output_data);
|
||||
|
||||
/**
|
||||
* @brief AES-ECB-128 encryption
|
||||
*
|
||||
* @param[in] input_key The encryption key. must be 16bytes.
|
||||
* @param[in] input_data The buffer holding the input data.
|
||||
* @param[in] input_len The length of a data unit in bytes.
|
||||
* This can be any length between 16 bytes and 2^31 bytes inclusive
|
||||
* (between 1 and 2^27 block cipher blocks).
|
||||
* @param[out] output_data The buffer holding the output data.
|
||||
* The buffer size must be larger than the size after padding by 16 byte multiples.
|
||||
*/
|
||||
void aes_ecb128_hard_encrypt(uint8_t *input_key, uint8_t *input_data, size_t input_len, uint8_t *output_data);
|
||||
|
||||
/**
|
||||
* @brief AES-ECB-192 decryption
|
||||
*
|
||||
* @param[in] input_key The decryption key. must be 24bytes.
|
||||
* @param[in] input_data The buffer holding the input data.
|
||||
* @param[in] input_len The length of a data unit in bytes.
|
||||
* This can be any length between 16 bytes and 2^31 bytes inclusive
|
||||
* (between 1 and 2^27 block cipher blocks).
|
||||
* @param[out] output_data The buffer holding the output data.
|
||||
* The buffer size must be larger than the size after padding by 16 byte multiples.
|
||||
*/
|
||||
void aes_ecb192_hard_decrypt(uint8_t *input_key, uint8_t *input_data, size_t input_len, uint8_t *output_data);
|
||||
|
||||
/**
|
||||
* @brief AES-ECB-192 encryption
|
||||
*
|
||||
* @param[in] input_key The encryption key. must be 24bytes.
|
||||
* @param[in] input_data The buffer holding the input data.
|
||||
* @param[in] input_len The length of a data unit in bytes.
|
||||
* This can be any length between 16 bytes and 2^31 bytes inclusive
|
||||
* (between 1 and 2^27 block cipher blocks).
|
||||
* @param[out] output_data The buffer holding the output data.
|
||||
* The buffer size must be larger than the size after padding by 16 byte multiples.
|
||||
*/
|
||||
void aes_ecb192_hard_encrypt(uint8_t *input_key, uint8_t *input_data, size_t input_len, uint8_t *output_data);
|
||||
|
||||
/**
|
||||
* @brief AES-ECB-256 decryption
|
||||
*
|
||||
* @param[in] input_key The decryption key. must be 32bytes.
|
||||
* @param[in] input_data The buffer holding the input data.
|
||||
* @param[in] input_len The length of a data unit in bytes.
|
||||
* This can be any length between 16 bytes and 2^31 bytes inclusive
|
||||
* (between 1 and 2^27 block cipher blocks).
|
||||
* @param[out] output_data The buffer holding the output data.
|
||||
* The buffer size must be larger than the size after padding by 16 byte multiples.
|
||||
*/
|
||||
void aes_ecb256_hard_decrypt(uint8_t *input_key, uint8_t *input_data, size_t input_len, uint8_t *output_data);
|
||||
|
||||
/**
|
||||
* @brief AES-ECB-256 encryption
|
||||
*
|
||||
* @param[in] input_key The encryption key. must be 32bytes.
|
||||
* @param[in] input_data The buffer holding the input data.
|
||||
* @param[in] input_len The length of a data unit in bytes.
|
||||
* This can be any length between 16 bytes and 2^31 bytes inclusive
|
||||
* (between 1 and 2^27 block cipher blocks).
|
||||
* @param[out] output_data The buffer holding the output data.
|
||||
* The buffer size must be larger than the size after padding by 16 byte multiples.
|
||||
*/
|
||||
void aes_ecb256_hard_encrypt(uint8_t *input_key, uint8_t *input_data, size_t input_len, uint8_t *output_data);
|
||||
|
||||
/**
|
||||
* @brief AES-CBC-128 decryption
|
||||
*
|
||||
* @param[in] context The cbc context to use for encryption or decryption.
|
||||
* @param[in] input_key The decryption key. must be 16bytes.
|
||||
* @param[in] input_data The buffer holding the input data.
|
||||
* @param[in] input_len The length of a data unit in bytes.
|
||||
* This can be any length between 16 bytes and 2^31 bytes inclusive
|
||||
* (between 1 and 2^27 block cipher blocks).
|
||||
* @param[out] output_data The buffer holding the output data.
|
||||
* The buffer size must be larger than the size after padding by 16 byte multiples.
|
||||
*/
|
||||
void aes_cbc128_hard_decrypt(cbc_context_t *context, uint8_t *input_data, size_t input_len, uint8_t *output_data);
|
||||
|
||||
/**
|
||||
* @brief AES-CBC-128 encryption
|
||||
*
|
||||
* @param[in] context The cbc context to use for encryption or decryption.
|
||||
* @param[in] input_key The encryption key. must be 16bytes.
|
||||
* @param[in] input_data The buffer holding the input data.
|
||||
* @param[in] input_len The length of a data unit in bytes.
|
||||
* This can be any length between 16 bytes and 2^31 bytes inclusive
|
||||
* (between 1 and 2^27 block cipher blocks).
|
||||
* @param[out] output_data The buffer holding the output data.
|
||||
* The buffer size must be larger than the size after padding by 16 byte multiples.
|
||||
*/
|
||||
void aes_cbc128_hard_encrypt(cbc_context_t *context, uint8_t *input_data, size_t input_len, uint8_t *output_data);
|
||||
|
||||
/**
|
||||
* @brief AES-CBC-192 decryption
|
||||
*
|
||||
* @param[in] context The cbc context to use for encryption or decryption.
|
||||
* @param[in] input_key The decryption key. must be 24bytes.
|
||||
* @param[in] input_data The buffer holding the input data.
|
||||
* @param[in] input_len The length of a data unit in bytes.
|
||||
* This can be any length between 16 bytes and 2^31 bytes inclusive
|
||||
* (between 1 and 2^27 block cipher blocks).
|
||||
* @param[out] output_data The buffer holding the output data.
|
||||
* The buffer size must be larger than the size after padding by 16 byte multiples.
|
||||
*/
|
||||
void aes_cbc192_hard_decrypt(cbc_context_t *context, uint8_t *input_data, size_t input_len, uint8_t *output_data);
|
||||
|
||||
/**
|
||||
* @brief AES-CBC-192 encryption
|
||||
*
|
||||
* @param[in] context The cbc context to use for encryption or decryption.
|
||||
* @param[in] input_key The encryption key. must be 24bytes.
|
||||
* @param[in] input_data The buffer holding the input data.
|
||||
* @param[in] input_len The length of a data unit in bytes.
|
||||
* This can be any length between 16 bytes and 2^31 bytes inclusive
|
||||
* (between 1 and 2^27 block cipher blocks).
|
||||
* @param[out] output_data The buffer holding the output data.
|
||||
* The buffer size must be larger than the size after padding by 16 byte multiples.
|
||||
*/
|
||||
void aes_cbc192_hard_encrypt(cbc_context_t *context, uint8_t *input_data, size_t input_len, uint8_t *output_data);
|
||||
|
||||
/**
|
||||
* @brief AES-CBC-256 decryption
|
||||
*
|
||||
* @param[in] context The cbc context to use for encryption or decryption.
|
||||
* @param[in] input_key The decryption key. must be 32bytes.
|
||||
* @param[in] input_data The buffer holding the input data.
|
||||
* @param[in] input_len The length of a data unit in bytes.
|
||||
* This can be any length between 16 bytes and 2^31 bytes inclusive
|
||||
* (between 1 and 2^27 block cipher blocks).
|
||||
* @param[out] output_data The buffer holding the output data.
|
||||
* The buffer size must be larger than the size after padding by 16 byte multiples.
|
||||
*/
|
||||
void aes_cbc256_hard_decrypt(cbc_context_t *context, uint8_t *input_data, size_t input_len, uint8_t *output_data);
|
||||
|
||||
/**
|
||||
* @brief AES-CBC-256 encryption
|
||||
*
|
||||
* @param[in] context The cbc context to use for encryption or decryption.
|
||||
* @param[in] input_key The encryption key. must be 32bytes.
|
||||
* @param[in] input_data The buffer holding the input data.
|
||||
* @param[in] input_len The length of a data unit in bytes.
|
||||
* This can be any length between 16 bytes and 2^31 bytes inclusive
|
||||
* (between 1 and 2^27 block cipher blocks).
|
||||
* @param[out] output_data The buffer holding the output data.
|
||||
* The buffer size must be larger than the size after padding by 16 byte multiples.
|
||||
*/
|
||||
void aes_cbc256_hard_encrypt(cbc_context_t *context, uint8_t *input_data, size_t input_len, uint8_t *output_data);
|
||||
|
||||
/**
|
||||
* @brief AES-GCM-128 decryption
|
||||
*
|
||||
* @param[in] context The gcm context to use for encryption or decryption.
|
||||
* @param[in] input_key The decryption key. must be 16bytes.
|
||||
* @param[in] input_data The buffer holding the input data.
|
||||
* @param[in] input_len The length of a data unit in bytes.
|
||||
* This can be any length between 16 bytes and 2^31 bytes inclusive
|
||||
* (between 1 and 2^27 block cipher blocks).
|
||||
* @param[out] output_data The buffer holding the output data.
|
||||
* @param[out] gcm_tag The buffer for holding the tag.The length of the tag must be 4 bytes.
|
||||
*/
|
||||
void aes_gcm128_hard_decrypt(gcm_context_t *context, uint8_t *input_data, size_t input_len, uint8_t *output_data, uint8_t *gcm_tag);
|
||||
|
||||
/**
|
||||
* @brief AES-GCM-128 encryption
|
||||
*
|
||||
* @param[in] context The gcm context to use for encryption or decryption.
|
||||
* @param[in] input_key The encryption key. must be 16bytes.
|
||||
* @param[in] input_data The buffer holding the input data.
|
||||
* @param[in] input_len The length of a data unit in bytes.
|
||||
* This can be any length between 16 bytes and 2^31 bytes inclusive
|
||||
* (between 1 and 2^27 block cipher blocks).
|
||||
* @param[out] output_data The buffer holding the output data.
|
||||
* @param[out] gcm_tag The buffer for holding the tag.The length of the tag must be 4 bytes.
|
||||
*/
|
||||
void aes_gcm128_hard_encrypt(gcm_context_t *context, uint8_t *input_data, size_t input_len, uint8_t *output_data, uint8_t *gcm_tag);
|
||||
|
||||
/**
|
||||
* @brief AES-GCM-192 decryption
|
||||
*
|
||||
* @param[in] context The gcm context to use for encryption or decryption.
|
||||
* @param[in] input_key The decryption key. must be 24bytes.
|
||||
* @param[in] input_data The buffer holding the input data.
|
||||
* @param[in] input_len The length of a data unit in bytes.
|
||||
* This can be any length between 16 bytes and 2^31 bytes inclusive
|
||||
* (between 1 and 2^27 block cipher blocks).
|
||||
* @param[out] output_data The buffer holding the output data.
|
||||
* @param[out] gcm_tag The buffer for holding the tag.The length of the tag must be 4 bytes.
|
||||
*/
|
||||
void aes_gcm192_hard_decrypt(gcm_context_t *context, uint8_t *input_data, size_t input_len, uint8_t *output_data, uint8_t *gcm_tag);
|
||||
|
||||
/**
|
||||
* @brief AES-GCM-192 encryption
|
||||
*
|
||||
* @param[in] context The gcm context to use for encryption or decryption.
|
||||
* @param[in] input_key The encryption key. must be 24bytes.
|
||||
* @param[in] input_data The buffer holding the input data.
|
||||
* @param[in] input_len The length of a data unit in bytes.
|
||||
* This can be any length between 16 bytes and 2^31 bytes inclusive
|
||||
* (between 1 and 2^27 block cipher blocks).
|
||||
* @param[out] output_data The buffer holding the output data.
|
||||
* @param[out] gcm_tag The buffer for holding the tag.The length of the tag must be 4 bytes.
|
||||
*/
|
||||
void aes_gcm192_hard_encrypt(gcm_context_t *context, uint8_t *input_data, size_t input_len, uint8_t *output_data, uint8_t *gcm_tag);
|
||||
|
||||
/**
|
||||
* @brief AES-GCM-256 decryption
|
||||
*
|
||||
* @param[in] context The gcm context to use for encryption or decryption.
|
||||
* @param[in] input_key The decryption key. must be 32bytes.
|
||||
* @param[in] input_data The buffer holding the input data.
|
||||
* @param[in] input_len The length of a data unit in bytes.
|
||||
* This can be any length between 16 bytes and 2^31 bytes inclusive
|
||||
* (between 1 and 2^27 block cipher blocks).
|
||||
* @param[out] output_data The buffer holding the output data.
|
||||
* @param[out] gcm_tag The buffer for holding the tag.The length of the tag must be 4 bytes.
|
||||
*/
|
||||
void aes_gcm256_hard_decrypt(gcm_context_t *context, uint8_t *input_data, size_t input_len, uint8_t *output_data, uint8_t *gcm_tag);
|
||||
|
||||
/**
|
||||
* @brief AES-GCM-256 encryption
|
||||
*
|
||||
* @param[in] context The gcm context to use for encryption or decryption.
|
||||
* @param[in] input_key The encryption key. must be 32bytes.
|
||||
* @param[in] input_data The buffer holding the input data.
|
||||
* @param[in] input_len The length of a data unit in bytes.
|
||||
* This can be any length between 16 bytes and 2^31 bytes inclusive
|
||||
* (between 1 and 2^27 block cipher blocks).
|
||||
* @param[out] output_data The buffer holding the output data.
|
||||
* @param[out] gcm_tag The buffer for holding the tag.The length of the tag must be 4 bytes.
|
||||
*/
|
||||
void aes_gcm256_hard_encrypt(gcm_context_t *context, uint8_t *input_data, size_t input_len, uint8_t *output_data, uint8_t *gcm_tag);
|
||||
|
||||
/**
|
||||
* @brief AES-ECB-128 decryption by dma
|
||||
*
|
||||
* @param[in] dma_receive_channel_num Dmac receive channel number.
|
||||
* @param[in] input_key The decryption key. must be 16bytes.
|
||||
* @param[in] input_data The buffer holding the input data.
|
||||
* @param[in] input_len The length of a data unit in bytes.
|
||||
* This can be any length between 16 bytes and 2^31 bytes inclusive
|
||||
* (between 1 and 2^27 block cipher blocks).
|
||||
* @param[out] output_data The buffer holding the output data.
|
||||
* The buffer size must be larger than the size after padding by 16 byte multiples.
|
||||
*/
|
||||
void aes_ecb128_hard_decrypt_dma(dmac_channel_number_t dma_receive_channel_num,
|
||||
uint8_t *input_key,
|
||||
uint8_t *input_data,
|
||||
size_t input_len,
|
||||
uint8_t *output_data);
|
||||
|
||||
/**
|
||||
* @brief AES-ECB-128 encryption by dma
|
||||
*
|
||||
* @param[in] dma_receive_channel_num Dmac receive channel number.
|
||||
* @param[in] input_key The encryption key. must be 16bytes.
|
||||
* @param[in] input_data The buffer holding the input data.
|
||||
* @param[in] input_len The length of a data unit in bytes.
|
||||
* This can be any length between 16 bytes and 2^31 bytes inclusive
|
||||
* (between 1 and 2^27 block cipher blocks).
|
||||
* @param[out] output_data The buffer holding the output data.
|
||||
* The buffer size must be larger than the size after padding by 16 byte multiples.
|
||||
*/
|
||||
void aes_ecb128_hard_encrypt_dma(dmac_channel_number_t dma_receive_channel_num,
|
||||
uint8_t *input_key,
|
||||
uint8_t *input_data,
|
||||
size_t input_len,
|
||||
uint8_t *output_data);
|
||||
|
||||
/**
|
||||
* @brief AES-ECB-192 decryption by dma
|
||||
*
|
||||
* @param[in] dma_receive_channel_num Dmac receive channel number.
|
||||
* @param[in] input_key The decryption key. must be 16bytes.
|
||||
* @param[in] input_data The buffer holding the input data.
|
||||
* @param[in] input_len The length of a data unit in bytes.
|
||||
* This can be any length between 16 bytes and 2^31 bytes inclusive
|
||||
* (between 1 and 2^27 block cipher blocks).
|
||||
* @param[out] output_data The buffer holding the output data.
|
||||
* The buffer size must be larger than the size after padding by 16 byte multiples.
|
||||
*/
|
||||
void aes_ecb192_hard_decrypt_dma(dmac_channel_number_t dma_receive_channel_num,
|
||||
uint8_t *input_key,
|
||||
uint8_t *input_data,
|
||||
size_t input_len,
|
||||
uint8_t *output_data);
|
||||
|
||||
/**
|
||||
* @brief AES-ECB-192 encryption by dma
|
||||
*
|
||||
* @param[in] dma_receive_channel_num Dmac receive channel number.
|
||||
* @param[in] input_key The encryption key. must be 16bytes.
|
||||
* @param[in] input_data The buffer holding the input data.
|
||||
* @param[in] input_len The length of a data unit in bytes.
|
||||
* This can be any length between 16 bytes and 2^31 bytes inclusive
|
||||
* (between 1 and 2^27 block cipher blocks).
|
||||
* @param[out] output_data The buffer holding the output data.
|
||||
* The buffer size must be larger than the size after padding by 16 byte multiples.
|
||||
*/
|
||||
void aes_ecb192_hard_encrypt_dma(dmac_channel_number_t dma_receive_channel_num,
|
||||
uint8_t *input_key,
|
||||
uint8_t *input_data,
|
||||
size_t input_len,
|
||||
uint8_t *output_data);
|
||||
|
||||
/**
|
||||
* @brief AES-ECB-256 decryption by dma
|
||||
*
|
||||
* @param[in] dma_receive_channel_num Dmac receive channel number.
|
||||
* @param[in] input_key The decryption key. must be 16bytes.
|
||||
* @param[in] input_data The buffer holding the input data.
|
||||
* @param[in] input_len The length of a data unit in bytes.
|
||||
* This can be any length between 16 bytes and 2^31 bytes inclusive
|
||||
* (between 1 and 2^27 block cipher blocks).
|
||||
* @param[out] output_data The buffer holding the output data.
|
||||
* The buffer size must be larger than the size after padding by 16 byte multiples.
|
||||
*/
|
||||
void aes_ecb256_hard_decrypt_dma(dmac_channel_number_t dma_receive_channel_num,
|
||||
uint8_t *input_key,
|
||||
uint8_t *input_data,
|
||||
size_t input_len,
|
||||
uint8_t *output_data);
|
||||
|
||||
/**
|
||||
* @brief AES-ECB-256 encryption by dma
|
||||
*
|
||||
* @param[in] dma_receive_channel_num Dmac receive channel number.
|
||||
* @param[in] input_key The encryption key. must be 16bytes.
|
||||
* @param[in] input_data The buffer holding the input data.
|
||||
* @param[in] input_len The length of a data unit in bytes.
|
||||
* This can be any length between 16 bytes and 2^31 bytes inclusive
|
||||
* (between 1 and 2^27 block cipher blocks).
|
||||
* @param[out] output_data The buffer holding the output data.
|
||||
* The buffer size must be larger than the size after padding by 16 byte multiples.
|
||||
*/
|
||||
void aes_ecb256_hard_encrypt_dma(dmac_channel_number_t dma_receive_channel_num,
|
||||
uint8_t *input_key,
|
||||
uint8_t *input_data,
|
||||
size_t input_len,
|
||||
uint8_t *output_data);
|
||||
|
||||
/**
|
||||
* @brief AES-CBC-128 decryption
|
||||
*
|
||||
* @param[in] dma_receive_channel_num Dmac receive channel number.
|
||||
* @param[in] context The cbc context to use for encryption or decryption.
|
||||
* @param[in] input_key The encryption key. must be 24bytes.
|
||||
* @param[in] input_data The buffer holding the input data.
|
||||
* @param[in] input_len The length of a data unit in bytes.
|
||||
* This can be any length between 16 bytes and 2^31 bytes inclusive
|
||||
* (between 1 and 2^27 block cipher blocks).
|
||||
* @param[out] output_data The buffer holding the output data.
|
||||
* The buffer size must be larger than the size after padding by 16 byte multiples.
|
||||
*/
|
||||
void aes_cbc128_hard_decrypt_dma(dmac_channel_number_t dma_receive_channel_num,
|
||||
cbc_context_t *context,
|
||||
uint8_t *input_data,
|
||||
size_t input_len,
|
||||
uint8_t *output_data);
|
||||
|
||||
/**
|
||||
* @brief AES-CBC-128 encryption
|
||||
*
|
||||
* @param[in] dma_receive_channel_num Dmac receive channel number.
|
||||
* @param[in] context The cbc context to use for encryption or decryption.
|
||||
* @param[in] input_key The encryption key. must be 24bytes.
|
||||
* @param[in] input_data The buffer holding the input data.
|
||||
* @param[in] input_len The length of a data unit in bytes.
|
||||
* This can be any length between 16 bytes and 2^31 bytes inclusive
|
||||
* (between 1 and 2^27 block cipher blocks).
|
||||
* @param[out] output_data The buffer holding the output data.
|
||||
* The buffer size must be larger than the size after padding by 16 byte multiples.
|
||||
*/
|
||||
void aes_cbc128_hard_encrypt_dma(dmac_channel_number_t dma_receive_channel_num,
|
||||
cbc_context_t *context,
|
||||
uint8_t *input_data,
|
||||
size_t input_len,
|
||||
uint8_t *output_data);
|
||||
|
||||
/**
|
||||
* @brief AES-CBC-192 decryption
|
||||
*
|
||||
* @param[in] dma_receive_channel_num Dmac receive channel number.
|
||||
* @param[in] context The cbc context to use for encryption or decryption.
|
||||
* @param[in] input_key The decryption key. must be 24bytes.
|
||||
* @param[in] input_data The buffer holding the input data.
|
||||
* @param[in] input_len The length of a data unit in bytes.
|
||||
* This can be any length between 16 bytes and 2^31 bytes inclusive
|
||||
* (between 1 and 2^27 block cipher blocks).
|
||||
* @param[out] output_data The buffer holding the output data.
|
||||
* The buffer size must be larger than the size after padding by 16 byte multiples.
|
||||
*/
|
||||
void aes_cbc192_hard_decrypt_dma(dmac_channel_number_t dma_receive_channel_num,
|
||||
cbc_context_t *context,
|
||||
uint8_t *input_data,
|
||||
size_t input_len,
|
||||
uint8_t *output_data);
|
||||
|
||||
/**
|
||||
* @brief AES-CBC-192 encryption
|
||||
*
|
||||
* @param[in] dma_receive_channel_num Dmac receive channel number.
|
||||
* @param[in] context The cbc context to use for encryption or decryption.
|
||||
* @param[in] input_key The encryption key. must be 24bytes.
|
||||
* @param[in] input_data The buffer holding the input data.
|
||||
* @param[in] input_len The length of a data unit in bytes.
|
||||
* This can be any length between 16 bytes and 2^31 bytes inclusive
|
||||
* (between 1 and 2^27 block cipher blocks).
|
||||
* @param[out] output_data The buffer holding the output data.
|
||||
* The buffer size must be larger than the size after padding by 16 byte multiples.
|
||||
*/
|
||||
void aes_cbc192_hard_encrypt_dma(dmac_channel_number_t dma_receive_channel_num,
|
||||
cbc_context_t *context,
|
||||
uint8_t *input_data,
|
||||
size_t input_len,
|
||||
uint8_t *output_data);
|
||||
|
||||
/**
|
||||
* @brief AES-CBC-256 decryption
|
||||
*
|
||||
* @param[in] dma_receive_channel_num Dmac receive channel number.
|
||||
* @param[in] context The cbc context to use for encryption or decryption.
|
||||
* @param[in] input_key The decryption key. must be 24bytes.
|
||||
* @param[in] input_data The buffer holding the input data.
|
||||
* @param[in] input_len The length of a data unit in bytes.
|
||||
* This can be any length between 16 bytes and 2^31 bytes inclusive
|
||||
* (between 1 and 2^27 block cipher blocks).
|
||||
* @param[out] output_data The buffer holding the output data.
|
||||
* The buffer size must be larger than the size after padding by 16 byte multiples.
|
||||
*/
|
||||
void aes_cbc256_hard_decrypt_dma(dmac_channel_number_t dma_receive_channel_num,
|
||||
cbc_context_t *context,
|
||||
uint8_t *input_data,
|
||||
size_t input_len,
|
||||
uint8_t *output_data);
|
||||
|
||||
/**
|
||||
* @brief AES-CBC-256 encryption
|
||||
*
|
||||
* @param[in] dma_receive_channel_num Dmac receive channel number.
|
||||
* @param[in] context The cbc context to use for encryption or decryption.
|
||||
* @param[in] input_key The encryption key. must be 24bytes.
|
||||
* @param[in] input_data The buffer holding the input data.
|
||||
* @param[in] input_len The length of a data unit in bytes.
|
||||
* This can be any length between 16 bytes and 2^31 bytes inclusive
|
||||
* (between 1 and 2^27 block cipher blocks).
|
||||
* @param[out] output_data The buffer holding the output data.
|
||||
* The buffer size must be larger than the size after padding by 16 byte multiples.
|
||||
*/
|
||||
void aes_cbc256_hard_encrypt_dma(dmac_channel_number_t dma_receive_channel_num,
|
||||
cbc_context_t *context,
|
||||
uint8_t *input_data,
|
||||
size_t input_len,
|
||||
uint8_t *output_data);
|
||||
|
||||
/**
|
||||
* @brief AES-GCM-128 decryption
|
||||
*
|
||||
* @param[in] dma_receive_channel_num Dmac receive channel number.
|
||||
* @param[in] context The gcm context to use for encryption or decryption.
|
||||
* @param[in] input_key The decryption key. must be 16bytes.
|
||||
* @param[in] input_data The buffer holding the input data.
|
||||
* @param[in] input_len The length of a data unit in bytes. Must be 4 byte multiples.
|
||||
* This can be any length between 16 bytes and 2^31 bytes inclusive
|
||||
* (between 1 and 2^27 block cipher blocks).
|
||||
* @param[out] output_data The buffer holding the output data.
|
||||
* @param[out] gcm_tag The buffer for holding the tag.The length of the tag must be 4 bytes.
|
||||
*/
|
||||
void aes_gcm128_hard_decrypt_dma(dmac_channel_number_t dma_receive_channel_num,
|
||||
gcm_context_t *context,
|
||||
uint8_t *input_data,
|
||||
size_t input_len,
|
||||
uint8_t *output_data,
|
||||
uint8_t *gcm_tag);
|
||||
|
||||
/**
|
||||
* @brief AES-GCM-128 encryption
|
||||
*
|
||||
* @param[in] dma_receive_channel_num Dmac receive channel number.
|
||||
* @param[in] context The gcm context to use for encryption or decryption.
|
||||
* @param[in] input_key The encryption key. must be 16bytes.
|
||||
* @param[in] input_data The buffer holding the input data.
|
||||
* @param[in] input_len The length of a data unit in bytes. Must be 4 byte multiples.
|
||||
* This can be any length between 16 bytes and 2^31 bytes inclusive
|
||||
* (between 1 and 2^27 block cipher blocks).
|
||||
* @param[out] output_data The buffer holding the output data.
|
||||
* @param[out] gcm_tag The buffer for holding the tag.The length of the tag must be 4 bytes.
|
||||
*/
|
||||
void aes_gcm128_hard_encrypt_dma(dmac_channel_number_t dma_receive_channel_num,
|
||||
gcm_context_t *context,
|
||||
uint8_t *input_data,
|
||||
size_t input_len,
|
||||
uint8_t *output_data,
|
||||
uint8_t *gcm_tag);
|
||||
|
||||
/**
|
||||
* @brief AES-GCM-192 decryption
|
||||
*
|
||||
* @param[in] dma_receive_channel_num Dmac receive channel number.
|
||||
* @param[in] context The gcm context to use for encryption or decryption.
|
||||
* @param[in] input_key The decryption key. must be 16bytes.
|
||||
* @param[in] input_data The buffer holding the input data.
|
||||
* @param[in] input_len The length of a data unit in bytes. Must be 4 byte multiples.
|
||||
* This can be any length between 16 bytes and 2^31 bytes inclusive
|
||||
* (between 1 and 2^27 block cipher blocks).
|
||||
* @param[out] output_data The buffer holding the output data.
|
||||
* @param[out] gcm_tag The buffer for holding the tag.The length of the tag must be 4 bytes.
|
||||
*/
|
||||
void aes_gcm192_hard_decrypt_dma(dmac_channel_number_t dma_receive_channel_num,
|
||||
gcm_context_t *context,
|
||||
uint8_t *input_data,
|
||||
size_t input_len,
|
||||
uint8_t *output_data,
|
||||
uint8_t *gcm_tag);
|
||||
|
||||
/**
|
||||
* @brief AES-GCM-192 encryption
|
||||
*
|
||||
* @param[in] dma_receive_channel_num Dmac receive channel number.
|
||||
* @param[in] context The gcm context to use for encryption or decryption.
|
||||
* @param[in] input_key The encryption key. must be 16bytes.
|
||||
* @param[in] input_data The buffer holding the input data.
|
||||
* @param[in] input_len The length of a data unit in bytes. Must be 4 byte multiples.
|
||||
* This can be any length between 16 bytes and 2^31 bytes inclusive
|
||||
* (between 1 and 2^27 block cipher blocks).
|
||||
* @param[out] output_data The buffer holding the output data.
|
||||
* @param[out] gcm_tag The buffer for holding the tag.The length of the tag must be 4 bytes.
|
||||
*/
|
||||
void aes_gcm192_hard_encrypt_dma(dmac_channel_number_t dma_receive_channel_num,
|
||||
gcm_context_t *context,
|
||||
uint8_t *input_data,
|
||||
size_t input_len,
|
||||
uint8_t *output_data,
|
||||
uint8_t *gcm_tag);
|
||||
|
||||
/**
|
||||
* @brief AES-GCM-256 decryption
|
||||
*
|
||||
* @param[in] dma_receive_channel_num Dmac receive channel number.
|
||||
* @param[in] context The gcm context to use for encryption or decryption.
|
||||
* @param[in] input_key The decryption key. must be 16bytes.
|
||||
* @param[in] input_data The buffer holding the input data.
|
||||
* @param[in] input_len The length of a data unit in bytes. Must be 4 byte multiples.
|
||||
* This can be any length between 16 bytes and 2^31 bytes inclusive
|
||||
* (between 1 and 2^27 block cipher blocks).
|
||||
* @param[out] output_data The buffer holding the output data.
|
||||
* @param[out] gcm_tag The buffer for holding the tag.The length of the tag must be 4 bytes.
|
||||
*/
|
||||
void aes_gcm256_hard_decrypt_dma(dmac_channel_number_t dma_receive_channel_num,
|
||||
gcm_context_t *context,
|
||||
uint8_t *input_data,
|
||||
size_t input_len,
|
||||
uint8_t *output_data,
|
||||
uint8_t *gcm_tag);
|
||||
|
||||
/**
|
||||
* @brief AES-GCM-256 encryption
|
||||
*
|
||||
* @param[in] dma_receive_channel_num Dmac receive channel number.
|
||||
* @param[in] context The gcm context to use for encryption or decryption.
|
||||
* @param[in] input_key The encryption key. must be 16bytes.
|
||||
* @param[in] input_data The buffer holding the input data.
|
||||
* @param[in] input_len The length of a data unit in bytes. Must be 4 byte multiples.
|
||||
* This can be any length between 16 bytes and 2^31 bytes inclusive
|
||||
* (between 1 and 2^27 block cipher blocks).
|
||||
* @param[out] output_data The buffer holding the output data.
|
||||
* @param[out] gcm_tag The buffer for holding the tag.The length of the tag must be 4 bytes.
|
||||
*/
|
||||
void aes_gcm256_hard_encrypt_dma(dmac_channel_number_t dma_receive_channel_num,
|
||||
gcm_context_t *context,
|
||||
uint8_t *input_data,
|
||||
size_t input_len,
|
||||
uint8_t *output_data,
|
||||
uint8_t *gcm_tag);
|
||||
|
||||
/**
|
||||
* @brief This function initializes the AES hard module.
|
||||
*
|
||||
* @param[in] input_key The buffer holding the encryption or decryption key.
|
||||
* @param[in] input_key_len The length of the input_key.must be 16bytes || 24bytes || 32bytes.
|
||||
* @param[in] iv The initialization vector.
|
||||
* @param[in] iv_len The length of the iv.GCM must be 12bytes. CBC must be 16bytes. ECB set 0L.
|
||||
* @param[in] gcm_aad The buffer holding the Additional authenticated data. or NULL
|
||||
* @param[in] cipher_mode Cipher Modes.must be AES_CBC || AES_ECB || AES_GCM.
|
||||
* Other cipher modes, please look forward to the next generation of kendryte.
|
||||
* @param[in] encrypt_sel The operation to perform:encryption or decryption.
|
||||
* @param[in] gcm_aad_len The length of the gcm_aad.
|
||||
* @param[in] input_data_len The length of the input_data.
|
||||
*/
|
||||
void aes_init(uint8_t *input_key, size_t input_key_len, uint8_t *iv,size_t iv_len, uint8_t *gcm_aad,
|
||||
aes_cipher_mode_t cipher_mode, aes_encrypt_sel_t encrypt_sel, size_t gcm_aad_len, size_t input_data_len);
|
||||
|
||||
/**
|
||||
* @brief This function feeds an input buffer into an encryption or decryption operation.
|
||||
*
|
||||
* @param[in] input_data The buffer holding the input data.
|
||||
* @param[out] output_data The buffer holding the output data.
|
||||
* @param[in] input_data_len The length of the input_data.
|
||||
* @param[in] cipher_mode Cipher Modes.must be AES_CBC || AES_ECB || AES_GCM.
|
||||
* Other cipher modes, please look forward to the next generation of kendryte.
|
||||
*/
|
||||
void aes_process(uint8_t *input_data, uint8_t *output_data, size_t input_data_len, aes_cipher_mode_t cipher_mode);
|
||||
|
||||
/**
|
||||
* @brief This function get the gcm tag to verify.
|
||||
*
|
||||
* @param[out] gcm_tag The buffer holding the gcm tag.The length of the tag must be 16bytes.
|
||||
*/
|
||||
void gcm_get_tag(uint8_t *gcm_tag);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _DRIVER_AES_H */
|
||||
@@ -1,323 +0,0 @@
|
||||
#ifndef _apu_H_
|
||||
#define _apu_H_
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern “C” {
|
||||
#endif
|
||||
|
||||
#define DIRECTION_RES 16
|
||||
#define I2S_FS 44100
|
||||
#define SOUND_SPEED 340
|
||||
|
||||
typedef enum en_bf_dir
|
||||
{
|
||||
APU_DIR0 = 0,
|
||||
APU_DIR1,
|
||||
APU_DIR2,
|
||||
APU_DIR3,
|
||||
APU_DIR4,
|
||||
APU_DIR5,
|
||||
APU_DIR6,
|
||||
APU_DIR7,
|
||||
APU_DIR8,
|
||||
APU_DIR9,
|
||||
APU_DIR10,
|
||||
APU_DIR11,
|
||||
APU_DIR12,
|
||||
APU_DIR13,
|
||||
APU_DIR14,
|
||||
APU_DIR15,
|
||||
} en_bf_dir_t;
|
||||
|
||||
typedef struct _apu_ch_cfg
|
||||
{
|
||||
/**
|
||||
* BF unit sound channel enable control bits.
|
||||
* Bit 'x' corresponds to enable bit for sound channel 'x' (x = 0, 1, 2,
|
||||
* . . ., 7). BF sound channels are related with I2S host RX channels.
|
||||
* BF sound channel 0/1 correspond to the left/right channel of I2S RX0;
|
||||
* BF channel 2/3 correspond to left/right channels of I2S RX1; and
|
||||
* things like that. 0x1: writing '1' to enable the corresponding BF
|
||||
* sound channel. 0x0: writing '0' to close the corresponding BF sound
|
||||
* channel.
|
||||
*/
|
||||
uint32_t bf_sound_ch_en : 8;
|
||||
/**
|
||||
* Target direction select for valid voice output.
|
||||
* When the source voice direaction searching is done, software can use
|
||||
* this field to select one from 16 sound directions for the following
|
||||
* voice recognition. 0x0: select sound direction 0; 0x1: select sound
|
||||
* direction 1; . . . . . . 0xF: select sound direction 15.
|
||||
*/
|
||||
uint32_t bf_target_dir : 4;
|
||||
/**
|
||||
* This is the audio sample gain factor. Using this gain factor to
|
||||
* enhance or reduce the stength of the sum of at most 8 source
|
||||
* sound channel outputs. This is a unsigned 11-bit fix-point number,
|
||||
* bit 10 is integer part and bit 9~0 are the fractional part.
|
||||
*/
|
||||
uint32_t audio_gain : 11;
|
||||
uint32_t reserved1 : 1;
|
||||
/**
|
||||
* audio data source configure parameter. This parameter controls where
|
||||
* the audio data source comes from. 0x0: audio data directly sourcing
|
||||
* from apu internal buffer; 0x1: audio data sourcing from
|
||||
* FFT result buffer.
|
||||
*/
|
||||
uint32_t data_src_mode : 1;
|
||||
uint32_t reserved2 : 3;
|
||||
/**
|
||||
* write enable for bf_sound_ch_en parameter.
|
||||
* 0x1: allowing updates made to 'bf_sound_ch_en'.
|
||||
* Access Mode: write only
|
||||
*/
|
||||
uint32_t we_bf_sound_ch_en : 1;
|
||||
/**
|
||||
* write enable for bf_target_dir parameter.
|
||||
* 0x1: allowing updates made to 'bf_target_dir'.
|
||||
* Access Mode: write only
|
||||
*/
|
||||
uint32_t we_bf_target_dir : 1;
|
||||
/**
|
||||
* write enable for audio_gain parameter.
|
||||
* 0x1: allowing updates made to 'audio_gain'.
|
||||
* Access Mode: write only
|
||||
*/
|
||||
uint32_t we_audio_gain : 1;
|
||||
/**
|
||||
* write enable for data_out_mode parameter.
|
||||
* 0x1: allowing updates made to 'data_src_mode'.
|
||||
*/
|
||||
uint32_t we_data_src_mode : 1;
|
||||
} __attribute__((packed, aligned(4))) apu_ch_cfg_t;
|
||||
|
||||
typedef struct _apu_ctl_t
|
||||
{
|
||||
/**
|
||||
* Sound direction searching enable bit.
|
||||
* Software writes '1' to start sound direction searching function.
|
||||
* When all the sound sample buffers are filled full, this bit is
|
||||
* cleared by hardware (this sample buffers are used for direction
|
||||
* detect only). 0x1: enable direction searching.
|
||||
*/
|
||||
uint32_t bf_dir_search_en : 1;
|
||||
/*
|
||||
*use this parameter to reset all the control logic on direction search processing path. This bit is self-clearing.
|
||||
* 0x1: apply reset to direction searching control logic;
|
||||
* 0x0: No operation.
|
||||
*/
|
||||
uint32_t search_path_reset : 1;
|
||||
uint32_t reserved : 2;
|
||||
/**
|
||||
* Valid voice sample stream generation enable bit.
|
||||
* After sound direction searching is done, software can configure this
|
||||
* bit to generate a stream of voice samples for voice recognition. 0x1:
|
||||
* enable output of voice sample stream. 0x0: stop the voice samlpe
|
||||
* stream output.
|
||||
*/
|
||||
uint32_t bf_stream_gen_en : 1;
|
||||
/*
|
||||
*use this parameter to reset all the control logic on voice stream generating path. This bit is self-clearing.
|
||||
* 0x1: apply reset to voice stream generating control logic;
|
||||
* 0x0: No operation.
|
||||
*/
|
||||
uint32_t voice_gen_path_reset : 1;
|
||||
/*
|
||||
*use this parameter to switch to a new voice source direction. Software write '1' here and hardware will automatically clear it.
|
||||
* 0x1: write '1' here to request switching to new voice source direction.
|
||||
*/
|
||||
uint32_t update_voice_dir : 1;
|
||||
|
||||
uint32_t reserved1 : 1;
|
||||
//write enable for 'bf_dir_search_en' parameter.
|
||||
uint32_t we_bf_dir_search_en : 1;
|
||||
uint32_t we_search_path_rst : 1;
|
||||
uint32_t we_bf_stream_gen : 1;
|
||||
uint32_t we_voice_gen_path_rst : 1;
|
||||
uint32_t we_update_voice_dir : 1;
|
||||
uint32_t reserved2 : 19;
|
||||
|
||||
} __attribute__((packed, aligned(4))) apu_ctl_t;
|
||||
|
||||
typedef struct _apu_dir_bidx
|
||||
{
|
||||
uint32_t dir_rd_idx0 : 6;
|
||||
uint32_t reserved : 2;
|
||||
uint32_t dir_rd_idx1 : 6;
|
||||
uint32_t reserved1 : 2;
|
||||
uint32_t dir_rd_idx2 : 6;
|
||||
uint32_t reserved2 : 2;
|
||||
uint32_t dir_rd_idx3 : 6;
|
||||
uint32_t reserved3 : 2;
|
||||
} __attribute__((packed, aligned(4))) apu_dir_bidx_t;
|
||||
|
||||
typedef struct _apu_fir_coef
|
||||
{
|
||||
uint32_t fir_tap0 : 16;
|
||||
uint32_t fir_tap1 : 16;
|
||||
} __attribute__((packed, aligned(4))) apu_fir_coef_t;
|
||||
|
||||
typedef struct _apu_dwsz_cfg
|
||||
{
|
||||
/**
|
||||
* TThe down-sizing ratio used for direction searching.
|
||||
* 0x0: no down-sizing;
|
||||
* 0x1: 1/2 down sizing;
|
||||
* 0x2: 1/3 down sizing;
|
||||
* . . . . . .
|
||||
* 0xF: 1/16 down sizing.
|
||||
*/
|
||||
uint32_t dir_dwn_siz_rate : 4;
|
||||
/**
|
||||
* The down-sizing ratio used for voice stream generation.
|
||||
* 0x0: no down-sizing;
|
||||
* 0x1: 1/2 down sizing;
|
||||
* 0x2: 1/3 down sizing;
|
||||
* . . . . . .
|
||||
* 0xF: 1/16 down sizing.
|
||||
*/
|
||||
uint32_t voc_dwn_siz_rate : 4;
|
||||
/**
|
||||
* This bit field is used to perform sample precision reduction when
|
||||
* the source sound sample (from I2S0 host receiving channels)
|
||||
* precision is 20/24/32 bits.
|
||||
* 0x0: take bits 15~0 from the source sound sample;
|
||||
* 0x1: take bits 16~1 from the source sound sample;
|
||||
* 0x2: take bits 17~2 from the source sound sample;
|
||||
* . . . . . .
|
||||
* 0x10: take bits 31~16 from the source sound sample;
|
||||
*/
|
||||
uint32_t smpl_shift_bits : 5;
|
||||
uint32_t reserved : 19;
|
||||
} __attribute__((packed, aligned(4))) apu_dwsz_cfg_t;
|
||||
|
||||
/*0x31c*/
|
||||
typedef struct _apu_fft_cfg
|
||||
{
|
||||
uint32_t fft_shift_factor : 9;
|
||||
uint32_t reserved1 : 3;
|
||||
uint32_t fft_enable : 1;
|
||||
uint32_t reserved2 : 19;
|
||||
} __attribute__((packed, aligned(4))) apu_fft_cfg_t;
|
||||
|
||||
/*0x328*/
|
||||
typedef struct _apu_int_stat
|
||||
{
|
||||
/**
|
||||
* sound direction searching data ready interrupt event.
|
||||
* Writing '1' to clear this interrupt event.
|
||||
* 0x1: data is ready for sound direction detect;
|
||||
* 0x0: no event.
|
||||
*/
|
||||
uint32_t dir_search_data_rdy : 1;
|
||||
/**
|
||||
* voice output stream buffer data ready interrupt event.
|
||||
* When a block of 512 voice samples are collected, this interrupt event
|
||||
* is asserted. Writing '1' to clear this interrupt event. 0x1: voice
|
||||
* output stream buffer data is ready; 0x0: no event.
|
||||
*/
|
||||
uint32_t voc_buf_data_rdy : 1;
|
||||
uint32_t reserved : 30;
|
||||
} __attribute__((packed, aligned(4))) apu_int_stat_t;
|
||||
|
||||
/*0x32c*/
|
||||
typedef struct _apu_int_mask
|
||||
{
|
||||
/**
|
||||
* This is the interrupt mask to dir searching data ready interrupt.
|
||||
* 0x1: mask off this interrupt;
|
||||
* 0x0: enable this interrupt.
|
||||
*/
|
||||
uint32_t dir_data_rdy_msk : 1;
|
||||
/**
|
||||
* This is the interrupt mask to voice output stream buffer ready
|
||||
* interrupt. 0x1: mask off this interrupt; 0x0: enable this interrupt.
|
||||
*/
|
||||
uint32_t voc_buf_rdy_msk : 1;
|
||||
uint32_t reserved : 30;
|
||||
} __attribute__((packed, aligned(4))) apu_int_mask_t;
|
||||
|
||||
typedef struct _apu_reg
|
||||
{
|
||||
//0x200
|
||||
apu_ch_cfg_t bf_ch_cfg_reg;
|
||||
//0x204
|
||||
apu_ctl_t bf_ctl_reg;
|
||||
//0x208
|
||||
apu_dir_bidx_t bf_dir_bidx[16][2];
|
||||
//0x288
|
||||
apu_fir_coef_t bf_pre_fir0_coef[9];
|
||||
//0x2ac
|
||||
apu_fir_coef_t bf_post_fir0_coef[9];
|
||||
//0x2d0
|
||||
apu_fir_coef_t bf_pre_fir1_coef[9];
|
||||
//0x2f4
|
||||
apu_fir_coef_t bf_post_fir1_coef[9];
|
||||
//0x318
|
||||
apu_dwsz_cfg_t bf_dwsz_cfg_reg;
|
||||
//0x31c
|
||||
apu_fft_cfg_t bf_fft_cfg_reg;
|
||||
// 0x320
|
||||
/**
|
||||
* This is the read register for system DMA to read data stored in
|
||||
* sample out buffers (the sample out buffers are used for sound
|
||||
* direction detect). Each data contains two sound samples.
|
||||
*/
|
||||
volatile uint32_t sobuf_dma_rdata;
|
||||
// 0x324
|
||||
/**
|
||||
* This is the read register for system DMA to read data stored in voice
|
||||
* out buffers (the voice out buffers are used for voice recognition).
|
||||
* Each data contains two sound samples.
|
||||
*/
|
||||
volatile uint32_t vobuf_dma_rdata;
|
||||
/*0x328*/
|
||||
apu_int_stat_t bf_int_stat_reg;
|
||||
/*0x32c*/
|
||||
apu_int_mask_t bf_int_mask_reg;
|
||||
/*0x330*/
|
||||
uint32_t saturation_counter;
|
||||
/*0x334*/
|
||||
uint32_t saturation_limits;
|
||||
} __attribute__((packed, aligned(4))) apu_reg_t;
|
||||
|
||||
extern volatile apu_reg_t *const apu;
|
||||
|
||||
void apu_set_audio_gain(uint16_t gain);
|
||||
void apu_set_smpl_shift(uint8_t smpl_shift);
|
||||
uint8_t apu_get_smpl_shift(void);
|
||||
void apu_set_channel_enabled(uint8_t channel_bit);
|
||||
void apu_set_direction_delay(uint8_t dir_num, uint8_t *dir_bidx);
|
||||
void apu_set_delay(float radius, uint8_t mic_num_a_circle, uint8_t center);
|
||||
|
||||
void apu_set_fft_shift_factor(uint8_t enable_flag, uint16_t shift_factor);
|
||||
void apu_set_down_size(uint8_t dir_dwn_siz, uint8_t voc_dwn_siz); /*split to 2 functions*/
|
||||
void apu_set_interrupt_mask(uint8_t dir_int_mask, uint8_t voc_int_mask); /*split to 2 functions*/
|
||||
|
||||
void apu_dir_enable(void);
|
||||
void apu_dir_reset(void);
|
||||
void apu_dir_set_prev_fir(uint16_t *fir_coef);
|
||||
void apu_dir_set_post_fir(uint16_t *fir_coef);
|
||||
void apu_dir_set_down_size(uint8_t dir_dwn_size);
|
||||
void apu_dir_set_interrupt_mask(uint8_t dir_int_mask);
|
||||
void apu_dir_clear_int_state(void);
|
||||
|
||||
void apu_voc_enable(uint8_t enable_flag);
|
||||
void apu_voc_reset(void);
|
||||
void apu_voc_set_direction(en_bf_dir_t direction);
|
||||
void apu_voc_set_prev_fir(uint16_t *fir_coef);
|
||||
void apu_voc_set_post_fir(uint16_t *fir_coef);
|
||||
void apu_voc_set_down_size(uint8_t voc_dwn_size);
|
||||
void apu_voc_set_interrupt_mask(uint8_t voc_int_mask);
|
||||
void apu_voc_clear_int_state(void);
|
||||
void apu_voc_reset_saturation_counter(void);
|
||||
uint32_t apu_voc_get_saturation_counter(void);
|
||||
void apu_voc_set_saturation_limit(uint16_t upper, uint16_t bottom);
|
||||
uint32_t apu_voc_get_saturation_limit(void);
|
||||
|
||||
void apu_print_setting(void);
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
@@ -1,338 +0,0 @@
|
||||
/* Copyright 2018 Canaan Inc.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* http://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.
|
||||
*/
|
||||
/**
|
||||
* @file
|
||||
* @brief The CLINT block holds memory-mapped control and status registers
|
||||
* associated with local interrupts for a Coreplex.
|
||||
*
|
||||
* @note CLINT RAM Layout
|
||||
*
|
||||
* | Address -| Description |
|
||||
* |------------|---------------------------------|
|
||||
* | 0x02000000 | msip for core 0 |
|
||||
* | 0x02000004 | msip for core 1 |
|
||||
* | ... | ... |
|
||||
* | 0x02003FF8 | msip for core 4094 |
|
||||
* | | |
|
||||
* | 0x02004000 | mtimecmp for core 0 |
|
||||
* | 0x02004008 | mtimecmp for core 1 |
|
||||
* | ... | ... |
|
||||
* | 0x0200BFF0 | mtimecmp For core 4094 |
|
||||
* | 0x0200BFF8 | mtime |
|
||||
* | | |
|
||||
* | 0x0200C000 | Reserved |
|
||||
* | ... | ... |
|
||||
* | 0x0200EFFC | Reserved |
|
||||
*/
|
||||
|
||||
#ifndef _DRIVER_CLINT_H
|
||||
#define _DRIVER_CLINT_H
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include "platform.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* clang-format off */
|
||||
/* Register address offsets */
|
||||
#define CLINT_MSIP (0x0000)
|
||||
#define CLINT_MSIP_SIZE (0x4)
|
||||
#define CLINT_MTIMECMP (0x4000)
|
||||
#define CLINT_MTIMECMP_SIZE (0x8)
|
||||
#define CLINT_MTIME (0xBFF8)
|
||||
#define CLINT_MTIME_SIZE (0x8)
|
||||
/* Max number of cores */
|
||||
#define CLINT_MAX_CORES (4095)
|
||||
/* Real number of cores */
|
||||
#define CLINT_NUM_CORES (2)
|
||||
/* Clock frequency division factor */
|
||||
#define CLINT_CLOCK_DIV (50)
|
||||
/* clang-format on */
|
||||
|
||||
/**
|
||||
* @brief MSIP Registers
|
||||
*
|
||||
* Machine-mode software interrupts are generated by writing to a
|
||||
* per-core memory-mapped control register. The msip registers are
|
||||
* 32-bit wide WARL registers, where the LSB is reflected in the
|
||||
* msip bit of the associated core’s mip register. Other bits in
|
||||
* the msip registers are hardwired to zero. The mapping supports
|
||||
* up to 4095 machine-mode cores.
|
||||
*/
|
||||
typedef struct _clint_msip
|
||||
{
|
||||
uint32_t msip : 1; /*!< Bit 0 is msip */
|
||||
uint32_t zero : 31; /*!< Bits [32:1] is 0 */
|
||||
} __attribute__((packed, aligned(4))) clint_msip_t;
|
||||
|
||||
/**
|
||||
* @brief Timer compare Registers Machine-mode timer interrupts are
|
||||
* generated by a real-time counter and a per-core comparator. The
|
||||
* mtime register is a 64-bit read-only register that contains the
|
||||
* current value of the real-time counter. Each mtimecmp register
|
||||
* holds its core’s time comparator. A timer interrupt is pending
|
||||
* whenever mtime is greater than or equal to the value in a
|
||||
* core’s mtimecmp register. The timer interrupt is reflected in
|
||||
* the mtip bit of the associated core’s mip register.
|
||||
*/
|
||||
typedef uint64_t clint_mtimecmp_t;
|
||||
|
||||
/**
|
||||
* @brief Timer Registers
|
||||
*
|
||||
* The mtime register has a 64-bit precision on all RV32, RV64,
|
||||
* and RV128 systems. Platforms provide a 64-bit memory-mapped
|
||||
* machine-mode timer compare register (mtimecmp), which causes a
|
||||
* timer interrupt to be posted when the mtime register contains a
|
||||
* value greater than or equal to the value in the mtimecmp
|
||||
* register. The interrupt remains posted until it is cleared by
|
||||
* writing the mtimecmp register. The interrupt will only be taken
|
||||
* if interrupts are enabled and the MTIE bit is set in the mie
|
||||
* register.
|
||||
*/
|
||||
typedef uint64_t clint_mtime_t;
|
||||
|
||||
/**
|
||||
* @brief CLINT object
|
||||
*
|
||||
* Coreplex-Local INTerrupts, which includes software interrupts,
|
||||
* local timer interrupts, and other interrupts routed directly to
|
||||
* a core.
|
||||
*/
|
||||
typedef struct _clint
|
||||
{
|
||||
/* 0x0000 to 0x3FF8, MSIP Registers */
|
||||
clint_msip_t msip[CLINT_MAX_CORES];
|
||||
/* Resverd space, do not use */
|
||||
uint32_t resv0;
|
||||
/* 0x4000 to 0xBFF0, Timer Compare Registers */
|
||||
clint_mtimecmp_t mtimecmp[CLINT_MAX_CORES];
|
||||
/* 0xBFF8, Time Register */
|
||||
clint_mtime_t mtime;
|
||||
} __attribute__((packed, aligned(4))) clint_t;
|
||||
|
||||
/**
|
||||
* @brief Clint object instanse
|
||||
*/
|
||||
extern volatile clint_t* const clint;
|
||||
|
||||
/**
|
||||
* @brief Definitions for the timer callbacks
|
||||
*/
|
||||
typedef int (*clint_timer_callback_t)(void *ctx);
|
||||
|
||||
/**
|
||||
* @brief Definitions for local interprocessor interrupt callbacks
|
||||
*/
|
||||
typedef int (*clint_ipi_callback_t)(void *ctx);
|
||||
|
||||
typedef struct _clint_timer_instance
|
||||
{
|
||||
uint64_t interval;
|
||||
uint64_t cycles;
|
||||
uint64_t single_shot;
|
||||
clint_timer_callback_t callback;
|
||||
void *ctx;
|
||||
} clint_timer_instance_t;
|
||||
|
||||
typedef struct _clint_ipi_instance
|
||||
{
|
||||
clint_ipi_callback_t callback;
|
||||
void *ctx;
|
||||
} clint_ipi_instance_t;
|
||||
|
||||
/**
|
||||
* @brief Get the time form CLINT timer register
|
||||
*
|
||||
* @note The CLINT must init to get right time
|
||||
*
|
||||
* @return 64bit Time
|
||||
*/
|
||||
uint64_t clint_get_time(void);
|
||||
|
||||
/**
|
||||
* @brief Init the CLINT timer
|
||||
*
|
||||
* @note MIP_MTIP will be clear after init. The MSTATUS_MIE must set by
|
||||
* user.
|
||||
*
|
||||
* @return result
|
||||
* - 0 Success
|
||||
* - Other Fail
|
||||
*/
|
||||
int clint_timer_init(void);
|
||||
|
||||
/**
|
||||
* @brief Stop the CLINT timer
|
||||
*
|
||||
* @note MIP_MTIP will be clear after stop
|
||||
*
|
||||
* @return result
|
||||
* - 0 Success
|
||||
* - Other Fail
|
||||
*/
|
||||
int clint_timer_stop(void);
|
||||
|
||||
/**
|
||||
* @brief Start the CLINT timer
|
||||
*
|
||||
* @param[in] interval The interval with Millisecond(ms)
|
||||
* @param[in] single_shot Single shot or repeat
|
||||
*
|
||||
* @return result
|
||||
* - 0 Success
|
||||
* - Other Fail
|
||||
*/
|
||||
int clint_timer_start(uint64_t interval, int single_shot);
|
||||
|
||||
/**
|
||||
* @brief Get the interval of timer
|
||||
*
|
||||
* @return The interval with Millisecond(ms)
|
||||
*/
|
||||
uint64_t clint_timer_get_interval(void);
|
||||
|
||||
/**
|
||||
* @brief Set the interval with Millisecond(ms)
|
||||
*
|
||||
* @param[in] interval The interval with Millisecond(ms)
|
||||
*
|
||||
* @return result
|
||||
* - 0 Success
|
||||
* - Other Fail
|
||||
*/
|
||||
int clint_timer_set_interval(uint64_t interval);
|
||||
|
||||
/**
|
||||
* @brief Get whether the timer is a single shot timer
|
||||
*
|
||||
* @return result
|
||||
* - 0 It is a repeat timer
|
||||
* - 1 It is a single shot timer
|
||||
*/
|
||||
int clint_timer_get_single_shot(void);
|
||||
|
||||
/**
|
||||
* @brief Set the timer working as a single shot timer or repeat timer
|
||||
*
|
||||
* @param[in] single_shot Single shot or repeat
|
||||
*
|
||||
* @return result
|
||||
* - 0 Success
|
||||
* - Other Fail
|
||||
*/
|
||||
int clint_timer_set_single_shot(int single_shot);
|
||||
|
||||
/**
|
||||
* @brief Set user callback function when timer is timeout
|
||||
*
|
||||
* @param[in] callback The callback function
|
||||
* @param[in] ctx The context
|
||||
*
|
||||
* @return result
|
||||
* - 0 Success
|
||||
* - Other Fail
|
||||
*/
|
||||
int clint_timer_register(clint_timer_callback_t callback, void *ctx);
|
||||
|
||||
/**
|
||||
* @brief Deregister user callback function
|
||||
*
|
||||
* @return result
|
||||
* - 0 Success
|
||||
* - Other Fail
|
||||
*/
|
||||
int clint_timer_unregister(void);
|
||||
|
||||
/**
|
||||
* @brief Initialize local interprocessor interrupt
|
||||
*
|
||||
* @return result
|
||||
* - 0 Success
|
||||
* - Other Fail
|
||||
*/
|
||||
int clint_ipi_init(void);
|
||||
|
||||
/**
|
||||
* @brief Enable local interprocessor interrupt
|
||||
*
|
||||
* @return result
|
||||
* - 0 Success
|
||||
* - Other Fail
|
||||
*/
|
||||
int clint_ipi_enable(void);
|
||||
|
||||
/**
|
||||
* @brief Disable local interprocessor interrupt
|
||||
*
|
||||
* @return result
|
||||
* - 0 Success
|
||||
* - Other Fail
|
||||
*/
|
||||
int clint_ipi_disable(void);
|
||||
|
||||
/**
|
||||
* @brief Send local interprocessor interrupt to core by core id
|
||||
*
|
||||
* @param[in] core_id The core identifier
|
||||
*
|
||||
* @return result
|
||||
* - 0 Success
|
||||
* - Other Fail
|
||||
*/
|
||||
int clint_ipi_send(size_t core_id);
|
||||
|
||||
/**
|
||||
* @brief Clear local interprocessor interrupt
|
||||
*
|
||||
* @param[in] core_id The core identifier
|
||||
*
|
||||
* @return result
|
||||
* - 1 An IPI was pending
|
||||
* - 0 Non IPI was pending
|
||||
* - -1 Fail
|
||||
*/
|
||||
int clint_ipi_clear(size_t core_id);
|
||||
|
||||
/**
|
||||
* @brief Set user callback function when interprocessor interrupt
|
||||
*
|
||||
* @param[in] callback The callback function
|
||||
* @param[in] ctx The context
|
||||
*
|
||||
* @return result
|
||||
* - 0 Success
|
||||
* - Other Fail
|
||||
*/
|
||||
int clint_ipi_register(clint_ipi_callback_t callback, void *ctx);
|
||||
|
||||
/**
|
||||
* @brief Deregister user callback function
|
||||
*
|
||||
* @return result
|
||||
* - 0 Success
|
||||
* - Other Fail
|
||||
*/
|
||||
int clint_ipi_unregister(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _DRIVER_CLINT_H */
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,269 +0,0 @@
|
||||
/* Copyright 2018 Canaan Inc.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* http://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 _DRIVER_DVP_H
|
||||
#define _DRIVER_DVP_H
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* clang-format off */
|
||||
/**
|
||||
* @brief DVP object
|
||||
*/
|
||||
typedef struct _dvp
|
||||
{
|
||||
uint32_t dvp_cfg;
|
||||
uint32_t r_addr;
|
||||
uint32_t g_addr;
|
||||
uint32_t b_addr;
|
||||
uint32_t cmos_cfg;
|
||||
uint32_t sccb_cfg;
|
||||
uint32_t sccb_ctl;
|
||||
uint32_t axi;
|
||||
uint32_t sts;
|
||||
uint32_t reverse;
|
||||
uint32_t rgb_addr;
|
||||
} __attribute__((packed, aligned(4))) dvp_t;
|
||||
|
||||
/* DVP Config Register */
|
||||
#define DVP_CFG_START_INT_ENABLE 0x00000001U
|
||||
#define DVP_CFG_FINISH_INT_ENABLE 0x00000002U
|
||||
#define DVP_CFG_AI_OUTPUT_ENABLE 0x00000004U
|
||||
#define DVP_CFG_DISPLAY_OUTPUT_ENABLE 0x00000008U
|
||||
#define DVP_CFG_AUTO_ENABLE 0x00000010U
|
||||
#define DVP_CFG_BURST_SIZE_4BEATS 0x00000100U
|
||||
#define DVP_CFG_FORMAT_MASK 0x00000600U
|
||||
#define DVP_CFG_RGB_FORMAT 0x00000000U
|
||||
#define DVP_CFG_YUV_FORMAT 0x00000200U
|
||||
#define DVP_CFG_Y_FORMAT 0x00000600U
|
||||
#define DVP_CFG_HREF_BURST_NUM_MASK 0x000FF000U
|
||||
#define DVP_CFG_HREF_BURST_NUM(x) ((x) << 12)
|
||||
#define DVP_CFG_LINE_NUM_MASK 0x3FF00000U
|
||||
#define DVP_CFG_LINE_NUM(x) ((x) << 20)
|
||||
|
||||
/* DVP CMOS Config Register */
|
||||
#define DVP_CMOS_CLK_DIV_MASK 0x000000FFU
|
||||
#define DVP_CMOS_CLK_DIV(x) ((x) << 0)
|
||||
#define DVP_CMOS_CLK_ENABLE 0x00000100U
|
||||
#define DVP_CMOS_RESET 0x00010000U
|
||||
#define DVP_CMOS_POWER_DOWN 0x01000000U
|
||||
|
||||
/* DVP SCCB Config Register */
|
||||
#define DVP_SCCB_BYTE_NUM_MASK 0x00000003U
|
||||
#define DVP_SCCB_BYTE_NUM_2 0x00000001U
|
||||
#define DVP_SCCB_BYTE_NUM_3 0x00000002U
|
||||
#define DVP_SCCB_BYTE_NUM_4 0x00000003U
|
||||
#define DVP_SCCB_SCL_LCNT_MASK 0x0000FF00U
|
||||
#define DVP_SCCB_SCL_LCNT(x) ((x) << 8)
|
||||
#define DVP_SCCB_SCL_HCNT_MASK 0x00FF0000U
|
||||
#define DVP_SCCB_SCL_HCNT(x) ((x) << 16)
|
||||
#define DVP_SCCB_RDATA_BYTE(x) ((x) >> 24)
|
||||
|
||||
/* DVP SCCB Control Register */
|
||||
#define DVP_SCCB_WRITE_DATA_ENABLE 0x00000001U
|
||||
#define DVP_SCCB_DEVICE_ADDRESS(x) ((x) << 0)
|
||||
#define DVP_SCCB_REG_ADDRESS(x) ((x) << 8)
|
||||
#define DVP_SCCB_WDATA_BYTE0(x) ((x) << 16)
|
||||
#define DVP_SCCB_WDATA_BYTE1(x) ((x) << 24)
|
||||
|
||||
/* DVP AXI Register */
|
||||
#define DVP_AXI_GM_MLEN_MASK 0x000000FFU
|
||||
#define DVP_AXI_GM_MLEN_1BYTE 0x00000000U
|
||||
#define DVP_AXI_GM_MLEN_4BYTE 0x00000003U
|
||||
|
||||
/* DVP STS Register */
|
||||
#define DVP_STS_FRAME_START 0x00000001U
|
||||
#define DVP_STS_FRAME_START_WE 0x00000002U
|
||||
#define DVP_STS_FRAME_FINISH 0x00000100U
|
||||
#define DVP_STS_FRAME_FINISH_WE 0x00000200U
|
||||
#define DVP_STS_DVP_EN 0x00010000U
|
||||
#define DVP_STS_DVP_EN_WE 0x00020000U
|
||||
#define DVP_STS_SCCB_EN 0x01000000U
|
||||
#define DVP_STS_SCCB_EN_WE 0x02000000U
|
||||
/* clang-format on */
|
||||
|
||||
typedef enum _dvp_output_mode
|
||||
{
|
||||
DVP_OUTPUT_AI,
|
||||
DVP_OUTPUT_DISPLAY,
|
||||
} dvp_output_mode_t;
|
||||
|
||||
/**
|
||||
* @brief DVP object instance
|
||||
*/
|
||||
extern volatile dvp_t* const dvp;
|
||||
|
||||
/**
|
||||
* @brief Initialize DVP
|
||||
*/
|
||||
void dvp_init(uint8_t reg_len);
|
||||
|
||||
/**
|
||||
* @brief Set image format
|
||||
*
|
||||
* @param[in] format The image format
|
||||
*/
|
||||
void dvp_set_image_format(uint32_t format);
|
||||
|
||||
/**
|
||||
* @brief Set image size
|
||||
*
|
||||
* @param[in] width The width of image
|
||||
* @param[in] height The height of image
|
||||
*/
|
||||
void dvp_set_image_size(uint32_t width, uint32_t height);
|
||||
|
||||
/**
|
||||
* @brief Set the address of RGB for AI
|
||||
*
|
||||
* @param[in] r_addr The R address of RGB
|
||||
* @param[in] g_addr The G address of RGB
|
||||
* @param[in] b_addr The B address of RGB
|
||||
*/
|
||||
void dvp_set_ai_addr(uint32_t r_addr, uint32_t g_addr, uint32_t b_addr);
|
||||
|
||||
/**
|
||||
* @brief Set the address of RGB for display
|
||||
*
|
||||
* @param[in] r_addr The R address of RGB
|
||||
* @param[in] g_addr The G address of RGB
|
||||
* @param[in] b_addr The B address of RGB
|
||||
*/
|
||||
void dvp_set_display_addr(uint32_t addr);
|
||||
|
||||
/**
|
||||
* @brief The frame start transfer
|
||||
*/
|
||||
void dvp_start_frame(void);
|
||||
|
||||
/**
|
||||
* @brief The DVP convert start
|
||||
*/
|
||||
void dvp_start_convert(void);
|
||||
|
||||
/**
|
||||
* @brief The DVP convert finish
|
||||
*/
|
||||
void dvp_finish_convert(void);
|
||||
|
||||
/**
|
||||
* @brief Get the image data
|
||||
*
|
||||
* @note The image data stored in the address of RGB
|
||||
*/
|
||||
void dvp_get_image(void);
|
||||
|
||||
/**
|
||||
* @brief Use SCCB write register
|
||||
*
|
||||
* @param[in] dev_addr The device address
|
||||
* @param[in] reg_addr The register address
|
||||
* @param[in] reg_data The register data
|
||||
*/
|
||||
void dvp_sccb_send_data(uint8_t dev_addr, uint16_t reg_addr, uint8_t reg_data);
|
||||
|
||||
/**
|
||||
* @brief Use SCCB read register
|
||||
*
|
||||
* @param[in] dev_addr The device address
|
||||
* @param[in] reg_addr The register address
|
||||
*
|
||||
* @return The register value
|
||||
*/
|
||||
uint8_t dvp_sccb_receive_data(uint8_t dev_addr, uint16_t reg_addr);
|
||||
|
||||
/**
|
||||
* @brief Enable dvp burst
|
||||
*/
|
||||
void dvp_enable_burst(void);
|
||||
|
||||
/**
|
||||
* @brief Disable dvp burst
|
||||
*/
|
||||
void dvp_disable_burst(void);
|
||||
|
||||
/**
|
||||
* @brief Enable or disable dvp interrupt
|
||||
*
|
||||
* @param[in] interrupt Dvp interrupt
|
||||
* @param[in] status 0:disable 1:enable
|
||||
*
|
||||
*/
|
||||
void dvp_config_interrupt(uint32_t interrupt, uint8_t enable);
|
||||
|
||||
/**
|
||||
* @brief Get dvp interrupt status
|
||||
*
|
||||
* @param[in] interrupt Dvp interrupt
|
||||
*
|
||||
*
|
||||
* @return Interrupt status
|
||||
* - 0 false
|
||||
* - 1 true
|
||||
*/
|
||||
int dvp_get_interrupt(uint32_t interrupt);
|
||||
|
||||
/**
|
||||
* @brief Clear dvp interrupt status
|
||||
*
|
||||
* @param[in] interrupt Dvp interrupt
|
||||
*
|
||||
*/
|
||||
void dvp_clear_interrupt(uint32_t interrupt);
|
||||
|
||||
/**
|
||||
* @brief Enable dvp auto mode
|
||||
*/
|
||||
void dvp_enable_auto(void);
|
||||
|
||||
/**
|
||||
* @brief Disable dvp auto mode
|
||||
*/
|
||||
void dvp_disable_auto(void);
|
||||
|
||||
/**
|
||||
* @brief Dvp ouput data enable or not
|
||||
*
|
||||
* @param[in] index 0:AI, 1:display
|
||||
* @param[in] enable 0:disable, 1:enable
|
||||
*
|
||||
*/
|
||||
void dvp_set_output_enable(dvp_output_mode_t index, int enable);
|
||||
|
||||
/**
|
||||
* @brief Set sccb clock rate
|
||||
*
|
||||
* @param[in] clk_rate Sccb clock rate
|
||||
*
|
||||
* @return The real sccb clock rate
|
||||
*/
|
||||
uint32_t dvp_sccb_set_clk_rate(uint32_t clk_rate);
|
||||
|
||||
/**
|
||||
* @brief Set xclk rate
|
||||
*
|
||||
* @param[in] clk_rate xclk rate
|
||||
*
|
||||
* @return The real xclk rate
|
||||
*/
|
||||
uint32_t dvp_set_xclk_rate(uint32_t xclk_rate);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _DRIVER_DVP_H */
|
||||
@@ -1,247 +0,0 @@
|
||||
/* Copyright 2018 Canaan Inc.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* http://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 _DRIVER_FFT_H
|
||||
#define _DRIVER_FFT_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include "platform.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct _complex_hard
|
||||
{
|
||||
int16_t real;
|
||||
int16_t imag;
|
||||
} complex_hard_t;
|
||||
|
||||
typedef struct _fft_data
|
||||
{
|
||||
int16_t I1;
|
||||
int16_t R1;
|
||||
int16_t I2;
|
||||
int16_t R2;
|
||||
} fft_data_t;
|
||||
|
||||
typedef enum _fft_point
|
||||
{
|
||||
FFT_512,
|
||||
FFT_256,
|
||||
FFT_128,
|
||||
FFT_64,
|
||||
} fft_point_t;
|
||||
|
||||
typedef enum _fft_direction
|
||||
{
|
||||
FFT_DIR_BACKWARD,
|
||||
FFT_DIR_FORWARD,
|
||||
FFT_DIR_MAX,
|
||||
} fft_direction_t;
|
||||
|
||||
/**
|
||||
* @brief FFT algorithm accelerator register
|
||||
*
|
||||
* @note FFT algorithm accelerator register table
|
||||
*
|
||||
* | Offset | Name | Description |
|
||||
* |-----------|----------------|-------------------------------------|
|
||||
* | 0x00 | fft_input_fifo | input data fifo |
|
||||
* | 0x08 | fft_ctrl | fft ctrl reg |
|
||||
* | 0x10 | fifo_ctrl | fifo ctrl |
|
||||
* | 0x18 | intr_mask | interrupt mask |
|
||||
* | 0x20 | intr_clear | interrupt clear |
|
||||
* | 0x28 | fft_status | fft status reg |
|
||||
* | 0x30 | fft_status_raw | fft_status_raw |
|
||||
* | 0x38 | fft_output_fifo| fft_output_fifo |
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief The calculation data is input through this register
|
||||
*
|
||||
* No. 0 Register (0x00)
|
||||
*/
|
||||
typedef struct _fft_input_fifo
|
||||
{
|
||||
uint64_t fft_input_fifo : 64;
|
||||
} __attribute__((packed, aligned(8))) fft_input_fifo_t;
|
||||
|
||||
/**
|
||||
* @brief fft ctrl reg
|
||||
*
|
||||
* No. 1 Register (0x08)
|
||||
*/
|
||||
typedef struct _fft_fft_ctrl
|
||||
{
|
||||
/**
|
||||
*FFT calculation data length:
|
||||
*b'000:512 point; b'001:256 point; b'010:128 point; b'011:64 point;
|
||||
*/
|
||||
uint64_t fft_point : 3;
|
||||
/* FFT mode: b'0:FFT b'1:IFFT */
|
||||
uint64_t fft_mode : 1;
|
||||
/* Corresponding to the nine layer butterfly shift operation, 0x0: does not shift; 0x1: shift 1st layer. ...*/
|
||||
uint64_t fft_shift : 9;
|
||||
/* FFT enable: b'0:disable b'1:enable */
|
||||
uint64_t fft_enable : 1;
|
||||
/* FFT DMA enable: b'0:disable b'1:enable */
|
||||
uint64_t dma_send : 1;
|
||||
/**
|
||||
*Input data arrangement: b'00:RIRI; b'01:only real part exist, RRRR;
|
||||
*b'10:First input the real part and then input the imaginary part.
|
||||
*/
|
||||
uint64_t fft_input_mode : 2;
|
||||
/* Effective width of input data. b'0:64bit effective; b'1:32bit effective */
|
||||
uint64_t fft_data_mode : 1;
|
||||
uint64_t reserved : 46;
|
||||
} __attribute__((packed, aligned(8))) fft_fft_ctrl_t;
|
||||
|
||||
/**
|
||||
* @brief fifo ctrl
|
||||
*
|
||||
* No. 2 Register (0x10)
|
||||
*/
|
||||
typedef struct _fft_fifo_ctrl
|
||||
{
|
||||
/* Response memory initialization flag.b'1:initialization */
|
||||
uint64_t resp_fifo_flush_n : 1;
|
||||
/* Command memory initialization flag.b'1:initialization */
|
||||
uint64_t cmd_fifo_flush_n : 1;
|
||||
/* Output interface memory initialization flag.b'1:initialization */
|
||||
uint64_t gs_fifo_flush_n : 1;
|
||||
uint64_t reserved : 61;
|
||||
} __attribute__((packed, aligned(8))) fft_fifo_ctrl_t;
|
||||
|
||||
/**
|
||||
* @brief interrupt mask
|
||||
*
|
||||
* No. 3 Register (0x18)
|
||||
*/
|
||||
typedef struct _fft_intr_mask
|
||||
{
|
||||
/**
|
||||
*FFT return status set.
|
||||
*b'0:FFT returns to the state after completion.
|
||||
*b'1:FFT does not return to the state after completion
|
||||
*/
|
||||
uint64_t fft_done_mask : 1;
|
||||
uint64_t reserved : 63;
|
||||
} __attribute__((packed, aligned(8))) fft_intr_mask_t;
|
||||
|
||||
/**
|
||||
* @brief interrupt clear
|
||||
*
|
||||
* No. 4 Register (0x20)
|
||||
*/
|
||||
typedef struct _fft_intr_clear
|
||||
{
|
||||
/* The interrupt state clears. b'1:clear current interrupt request */
|
||||
uint64_t fft_done_clear : 1;
|
||||
uint64_t reserved1 : 63;
|
||||
} __attribute__((packed, aligned(8))) fft_intr_clear_t;
|
||||
|
||||
/**
|
||||
* @brief fft status reg
|
||||
*
|
||||
* No. 5 Register (0x28)
|
||||
*/
|
||||
typedef struct _fft_status
|
||||
{
|
||||
/* FFT calculation state.b'0:not completed; b'1:completed */
|
||||
uint64_t fft_done_status : 1;
|
||||
uint64_t reserved1 : 63;
|
||||
} __attribute__((packed, aligned(8))) fft_status_t;
|
||||
|
||||
/**
|
||||
* @brief fft status raw
|
||||
*
|
||||
* No. 6 Register (0x30)
|
||||
*/
|
||||
typedef struct _fft_status_raw
|
||||
{
|
||||
/* FFT calculation state. b'1:done */
|
||||
uint64_t fft_done_status_raw : 1;
|
||||
/* FFT calculation state. b'1:working */
|
||||
uint64_t fft_work_status_raw : 1;
|
||||
uint64_t reserved : 62;
|
||||
} __attribute__((packed, aligned(8))) fft_status_raw_t;
|
||||
|
||||
/**
|
||||
* @brief Output of FFT calculation data through this register
|
||||
*
|
||||
* No. 7 Register (0x38)
|
||||
*/
|
||||
typedef struct _fft_output_fifo
|
||||
{
|
||||
uint64_t fft_output_fifo : 64;
|
||||
} __attribute__((packed, aligned(8))) fft_output_fifo_t;
|
||||
|
||||
/**
|
||||
* @brief Fast Fourier transform (FFT) algorithm accelerator object
|
||||
*
|
||||
* A fast Fourier transform (FFT) algorithm computes the discrete
|
||||
* Fourier transform (DFT) of a sequence, or its inverse (IFFT).
|
||||
* Fourier analysis converts a signal from its original domain
|
||||
* (often time or space) to a representation in the frequency
|
||||
* domain and vice versa. An FFT rapidly computes such
|
||||
* transformations by factorizing the DFT matrix into a product of
|
||||
* sparse (mostly zero) factors.
|
||||
*/
|
||||
typedef struct _fft
|
||||
{
|
||||
/* No. 0 (0x00): input data fifo */
|
||||
fft_input_fifo_t fft_input_fifo;
|
||||
/* No. 1 (0x08): fft ctrl reg */
|
||||
fft_fft_ctrl_t fft_ctrl;
|
||||
/* No. 2 (0x10): fifo ctrl */
|
||||
fft_fifo_ctrl_t fifo_ctrl;
|
||||
/* No. 3 (0x18): interrupt mask */
|
||||
fft_intr_mask_t intr_mask;
|
||||
/* No. 4 (0x20): interrupt clear */
|
||||
fft_intr_clear_t intr_clear;
|
||||
/* No. 5 (0x28): fft status reg */
|
||||
fft_status_t fft_status;
|
||||
/* No. 6 (0x30): fft_status_raw */
|
||||
fft_status_raw_t fft_status_raw;
|
||||
/* No. 7 (0x38): fft_output_fifo */
|
||||
fft_output_fifo_t fft_output_fifo;
|
||||
} __attribute__((packed, aligned(8))) fft_t;
|
||||
|
||||
/**
|
||||
* @brief Do 16bit quantized complex FFT by DMA
|
||||
*
|
||||
* @param[in] dma_send_channel_num Dmac send channel number.
|
||||
* @param[in] dma_receive_channel_num Dmac receive channel number.
|
||||
* @param[in] shift The shifts selection in 9 stage
|
||||
* @param[in] direction The direction
|
||||
* @param[in] input The input data
|
||||
* @param[in] point The FFT points count
|
||||
* @param[out] output The output data
|
||||
*/
|
||||
void fft_complex_uint16_dma(dmac_channel_number_t dma_send_channel_num,
|
||||
dmac_channel_number_t dma_receive_channel_num,
|
||||
uint16_t shift,
|
||||
fft_direction_t direction,
|
||||
const uint64_t *input,
|
||||
size_t point_num,
|
||||
uint64_t *output);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _DRIVER_FFT_H */
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,168 +0,0 @@
|
||||
/* Copyright 2018 Canaan Inc.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* http://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 _DRIVER_GPIO_H
|
||||
#define _DRIVER_GPIO_H
|
||||
|
||||
#include "platform.h"
|
||||
#include <inttypes.h>
|
||||
#include <stddef.h>
|
||||
#include "gpio_common.h"
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Structure for accessing GPIO registers by individual bit
|
||||
*/
|
||||
typedef struct _gpio_bits
|
||||
{
|
||||
uint32_t b0 : 1;
|
||||
uint32_t b1 : 1;
|
||||
uint32_t b2 : 1;
|
||||
uint32_t b3 : 1;
|
||||
uint32_t b4 : 1;
|
||||
uint32_t b5 : 1;
|
||||
uint32_t b6 : 1;
|
||||
uint32_t b7 : 1;
|
||||
uint32_t b8 : 1;
|
||||
uint32_t b9 : 1;
|
||||
uint32_t b10 : 1;
|
||||
uint32_t b11 : 1;
|
||||
uint32_t b12 : 1;
|
||||
uint32_t b13 : 1;
|
||||
uint32_t b14 : 1;
|
||||
uint32_t b15 : 1;
|
||||
uint32_t b16 : 1;
|
||||
uint32_t b17 : 1;
|
||||
uint32_t b18 : 1;
|
||||
uint32_t b19 : 1;
|
||||
uint32_t b20 : 1;
|
||||
uint32_t b21 : 1;
|
||||
uint32_t b22 : 1;
|
||||
uint32_t b23 : 1;
|
||||
uint32_t b24 : 1;
|
||||
uint32_t b25 : 1;
|
||||
uint32_t b26 : 1;
|
||||
uint32_t b27 : 1;
|
||||
uint32_t b28 : 1;
|
||||
uint32_t b29 : 1;
|
||||
uint32_t b30 : 1;
|
||||
uint32_t b31 : 1;
|
||||
} __attribute__((packed, aligned(4))) gpio_bits_t;
|
||||
|
||||
/**
|
||||
* @brief Structure of templates for accessing GPIO registers
|
||||
*/
|
||||
typedef union _gpio_access_tp
|
||||
{
|
||||
/* 32x1 bit mode */
|
||||
uint32_t u32[1];
|
||||
/* 16x2 bit mode */
|
||||
uint16_t u16[2];
|
||||
/* 8x4 bit mode */
|
||||
uint8_t u8[4];
|
||||
/* 1 bit mode */
|
||||
gpio_bits_t bits;
|
||||
} __attribute__((packed, aligned(4))) gpio_access_tp_t;
|
||||
|
||||
/**
|
||||
* @brief The GPIO address map
|
||||
*/
|
||||
typedef struct _gpio
|
||||
{
|
||||
/* Offset 0x00: Data (output) registers */
|
||||
gpio_access_tp_t data_output;
|
||||
/* Offset 0x04: Data direction registers */
|
||||
gpio_access_tp_t direction;
|
||||
/* Offset 0x08: Data source registers */
|
||||
gpio_access_tp_t source;
|
||||
/* Offset 0x10 - 0x2f: Unused registers, 9x4 bytes */
|
||||
uint32_t unused_0[9];
|
||||
/* Offset 0x30: Interrupt enable/disable registers */
|
||||
gpio_access_tp_t interrupt_enable;
|
||||
/* Offset 0x34: Interrupt mask registers */
|
||||
gpio_access_tp_t interrupt_mask;
|
||||
/* Offset 0x38: Interrupt level registers */
|
||||
gpio_access_tp_t interrupt_level;
|
||||
/* Offset 0x3c: Interrupt polarity registers */
|
||||
gpio_access_tp_t interrupt_polarity;
|
||||
/* Offset 0x40: Interrupt status registers */
|
||||
gpio_access_tp_t interrupt_status;
|
||||
/* Offset 0x44: Raw interrupt status registers */
|
||||
gpio_access_tp_t interrupt_status_raw;
|
||||
/* Offset 0x48: Interrupt debounce registers */
|
||||
gpio_access_tp_t interrupt_debounce;
|
||||
/* Offset 0x4c: Registers for clearing interrupts */
|
||||
gpio_access_tp_t interrupt_clear;
|
||||
/* Offset 0x50: External port (data input) registers */
|
||||
gpio_access_tp_t data_input;
|
||||
/* Offset 0x54 - 0x5f: Unused registers, 3x4 bytes */
|
||||
uint32_t unused_1[3];
|
||||
/* Offset 0x60: Sync level registers */
|
||||
gpio_access_tp_t sync_level;
|
||||
/* Offset 0x64: ID code */
|
||||
gpio_access_tp_t id_code;
|
||||
/* Offset 0x68: Interrupt both edge type */
|
||||
gpio_access_tp_t interrupt_bothedge;
|
||||
|
||||
} __attribute__((packed, aligned(4))) gpio_t;
|
||||
|
||||
/**
|
||||
* @brief Bus GPIO object instance
|
||||
*/
|
||||
extern volatile gpio_t *const gpio;
|
||||
|
||||
/**
|
||||
* @brief Gpio initialize
|
||||
*
|
||||
* @return Result
|
||||
* - 0 Success
|
||||
* - Other Fail
|
||||
*/
|
||||
int gpio_init(void);
|
||||
|
||||
/**
|
||||
* @brief Set Gpio drive mode
|
||||
*
|
||||
* @param[in] pin Gpio pin
|
||||
* @param[in] mode Gpio pin drive mode
|
||||
*/
|
||||
void gpio_set_drive_mode(uint8_t pin, gpio_drive_mode_t mode);
|
||||
|
||||
/**
|
||||
* @brief Get Gpio pin value
|
||||
*
|
||||
* @param[in] pin Gpio pin
|
||||
* @return Pin value
|
||||
*
|
||||
* - GPIO_PV_Low Gpio pin low
|
||||
* - GPIO_PV_High Gpio pin high
|
||||
*/
|
||||
gpio_pin_value_t gpio_get_pin(uint8_t pin);
|
||||
|
||||
/**
|
||||
* @brief Set Gpio pin value
|
||||
*
|
||||
* @param[in] pin Gpio pin
|
||||
* @param[in] value Gpio pin value
|
||||
*/
|
||||
void gpio_set_pin(uint8_t pin, gpio_pin_value_t value);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _DRIVER_GPIO_H */
|
||||
|
||||
@@ -1,51 +0,0 @@
|
||||
/* Copyright 2018 Canaan Inc.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* http://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 _GPIO_COMMON_H
|
||||
#define _GPIO_COMMON_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef enum _gpio_drive_mode
|
||||
{
|
||||
GPIO_DM_INPUT,
|
||||
GPIO_DM_INPUT_PULL_DOWN,
|
||||
GPIO_DM_INPUT_PULL_UP,
|
||||
GPIO_DM_OUTPUT,
|
||||
} gpio_drive_mode_t;
|
||||
|
||||
typedef enum _gpio_pin_edge
|
||||
{
|
||||
GPIO_PE_NONE,
|
||||
GPIO_PE_FALLING,
|
||||
GPIO_PE_RISING,
|
||||
GPIO_PE_BOTH,
|
||||
GPIO_PE_LOW,
|
||||
GPIO_PE_HIGH = 8,
|
||||
} gpio_pin_edge_t;
|
||||
|
||||
typedef enum _gpio_pin_value
|
||||
{
|
||||
GPIO_PV_LOW,
|
||||
GPIO_PV_HIGH
|
||||
} gpio_pin_value_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _GPIO_COMMON_H */
|
||||
|
||||
@@ -1,267 +0,0 @@
|
||||
/* Copyright 2018 Canaan Inc.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* http://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 _DRIVER_GPIOHS_H
|
||||
#define _DRIVER_GPIOHS_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include "platform.h"
|
||||
#include <stddef.h>
|
||||
#include "gpio_common.h"
|
||||
#include "plic.h"
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* clang-format off */
|
||||
/* Register address offsets */
|
||||
#define GPIOHS_INPUT_VAL (0x00)
|
||||
#define GPIOHS_INPUT_EN (0x04)
|
||||
#define GPIOHS_OUTPUT_EN (0x08)
|
||||
#define GPIOHS_OUTPUT_VAL (0x0C)
|
||||
#define GPIOHS_PULLUP_EN (0x10)
|
||||
#define GPIOHS_DRIVE (0x14)
|
||||
#define GPIOHS_RISE_IE (0x18)
|
||||
#define GPIOHS_RISE_IP (0x1C)
|
||||
#define GPIOHS_FALL_IE (0x20)
|
||||
#define GPIOHS_FALL_IP (0x24)
|
||||
#define GPIOHS_HIGH_IE (0x28)
|
||||
#define GPIOHS_HIGH_IP (0x2C)
|
||||
#define GPIOHS_LOW_IE (0x30)
|
||||
#define GPIOHS_LOW_IP (0x34)
|
||||
#define GPIOHS_IOF_EN (0x38)
|
||||
#define GPIOHS_IOF_SEL (0x3C)
|
||||
#define GPIOHS_OUTPUT_XOR (0x40)
|
||||
/* clang-format on */
|
||||
|
||||
/**
|
||||
* @brief GPIO bits raw object
|
||||
*/
|
||||
typedef struct _gpiohs_raw
|
||||
{
|
||||
/* Address offset 0x00 */
|
||||
uint32_t input_val;
|
||||
/* Address offset 0x04 */
|
||||
uint32_t input_en;
|
||||
/* Address offset 0x08 */
|
||||
uint32_t output_en;
|
||||
/* Address offset 0x0c */
|
||||
uint32_t output_val;
|
||||
/* Address offset 0x10 */
|
||||
uint32_t pullup_en;
|
||||
/* Address offset 0x14 */
|
||||
uint32_t drive;
|
||||
/* Address offset 0x18 */
|
||||
uint32_t rise_ie;
|
||||
/* Address offset 0x1c */
|
||||
uint32_t rise_ip;
|
||||
/* Address offset 0x20 */
|
||||
uint32_t fall_ie;
|
||||
/* Address offset 0x24 */
|
||||
uint32_t fall_ip;
|
||||
/* Address offset 0x28 */
|
||||
uint32_t high_ie;
|
||||
/* Address offset 0x2c */
|
||||
uint32_t high_ip;
|
||||
/* Address offset 0x30 */
|
||||
uint32_t low_ie;
|
||||
/* Address offset 0x34 */
|
||||
uint32_t low_ip;
|
||||
/* Address offset 0x38 */
|
||||
uint32_t iof_en;
|
||||
/* Address offset 0x3c */
|
||||
uint32_t iof_sel;
|
||||
/* Address offset 0x40 */
|
||||
uint32_t output_xor;
|
||||
} __attribute__((packed, aligned(4))) gpiohs_raw_t;
|
||||
|
||||
/**
|
||||
* @brief GPIO bits object
|
||||
*/
|
||||
typedef struct _gpiohs_bits
|
||||
{
|
||||
uint32_t b0 : 1;
|
||||
uint32_t b1 : 1;
|
||||
uint32_t b2 : 1;
|
||||
uint32_t b3 : 1;
|
||||
uint32_t b4 : 1;
|
||||
uint32_t b5 : 1;
|
||||
uint32_t b6 : 1;
|
||||
uint32_t b7 : 1;
|
||||
uint32_t b8 : 1;
|
||||
uint32_t b9 : 1;
|
||||
uint32_t b10 : 1;
|
||||
uint32_t b11 : 1;
|
||||
uint32_t b12 : 1;
|
||||
uint32_t b13 : 1;
|
||||
uint32_t b14 : 1;
|
||||
uint32_t b15 : 1;
|
||||
uint32_t b16 : 1;
|
||||
uint32_t b17 : 1;
|
||||
uint32_t b18 : 1;
|
||||
uint32_t b19 : 1;
|
||||
uint32_t b20 : 1;
|
||||
uint32_t b21 : 1;
|
||||
uint32_t b22 : 1;
|
||||
uint32_t b23 : 1;
|
||||
uint32_t b24 : 1;
|
||||
uint32_t b25 : 1;
|
||||
uint32_t b26 : 1;
|
||||
uint32_t b27 : 1;
|
||||
uint32_t b28 : 1;
|
||||
uint32_t b29 : 1;
|
||||
uint32_t b30 : 1;
|
||||
uint32_t b31 : 1;
|
||||
} __attribute__((packed, aligned(4))) gpiohs_bits_t;
|
||||
|
||||
/**
|
||||
* @brief GPIO bits multi access union
|
||||
*/
|
||||
typedef union _gpiohs_u32
|
||||
{
|
||||
/* 32x1 bit mode */
|
||||
uint32_t u32[1];
|
||||
/* 16x2 bit mode */
|
||||
uint16_t u16[2];
|
||||
/* 8x4 bit mode */
|
||||
uint8_t u8[4];
|
||||
/* 1 bit mode */
|
||||
gpiohs_bits_t bits;
|
||||
} __attribute__((packed, aligned(4))) gpiohs_u32_t;
|
||||
|
||||
/**
|
||||
* @brief GPIO object
|
||||
*
|
||||
* The GPIO controller is a peripheral device mapped in the
|
||||
* internal memory map, discoverable in the Configuration String.
|
||||
* It is responsible for low-level configuration of the actual
|
||||
* GPIO pads on the device (direction, pull up-enable, and drive
|
||||
* value), as well as selecting between various sources of the
|
||||
* controls for these signals. The GPIO controller allows seperate
|
||||
* configuration of each of N GPIO bits.
|
||||
*
|
||||
* Once the interrupt is pending, it will remain set until a 1 is
|
||||
* written to the *_ip register at that bit.
|
||||
*/
|
||||
|
||||
typedef struct _gpiohs
|
||||
{
|
||||
/* Address offset 0x00, Input Values */
|
||||
gpiohs_u32_t input_val;
|
||||
/* Address offset 0x04, Input enable */
|
||||
gpiohs_u32_t input_en;
|
||||
/* Address offset 0x08, Output enable */
|
||||
gpiohs_u32_t output_en;
|
||||
/* Address offset 0x0c, Onput Values */
|
||||
gpiohs_u32_t output_val;
|
||||
/* Address offset 0x10, Internal Pull-Ups enable */
|
||||
gpiohs_u32_t pullup_en;
|
||||
/* Address offset 0x14, Drive Strength */
|
||||
gpiohs_u32_t drive;
|
||||
/* Address offset 0x18, Rise interrupt enable */
|
||||
gpiohs_u32_t rise_ie;
|
||||
/* Address offset 0x1c, Rise interrupt pending */
|
||||
gpiohs_u32_t rise_ip;
|
||||
/* Address offset 0x20, Fall interrupt enable */
|
||||
gpiohs_u32_t fall_ie;
|
||||
/* Address offset 0x24, Fall interrupt pending */
|
||||
gpiohs_u32_t fall_ip;
|
||||
/* Address offset 0x28, High interrupt enable */
|
||||
gpiohs_u32_t high_ie;
|
||||
/* Address offset 0x2c, High interrupt pending */
|
||||
gpiohs_u32_t high_ip;
|
||||
/* Address offset 0x30, Low interrupt enable */
|
||||
gpiohs_u32_t low_ie;
|
||||
/* Address offset 0x34, Low interrupt pending */
|
||||
gpiohs_u32_t low_ip;
|
||||
/* Address offset 0x38, HW I/O Function enable */
|
||||
gpiohs_u32_t iof_en;
|
||||
/* Address offset 0x3c, HW I/O Function select */
|
||||
gpiohs_u32_t iof_sel;
|
||||
/* Address offset 0x40, Output XOR (invert) */
|
||||
gpiohs_u32_t output_xor;
|
||||
} __attribute__((packed, aligned(4))) gpiohs_t;
|
||||
|
||||
/**
|
||||
* @brief GPIO High-speed object instanse
|
||||
*/
|
||||
extern volatile gpiohs_t *const gpiohs;
|
||||
|
||||
/**
|
||||
* @brief Set Gpiohs drive mode
|
||||
*
|
||||
* @param[in] pin Gpiohs pin
|
||||
* @param[in] mode Gpiohs pin drive mode
|
||||
*/
|
||||
void gpiohs_set_drive_mode(uint8_t pin, gpio_drive_mode_t mode);
|
||||
|
||||
/**
|
||||
* @brief Get Gpiohs pin value
|
||||
*
|
||||
* @param[in] pin Gpiohs pin
|
||||
* @return Pin value
|
||||
*
|
||||
* - GPIO_PV_Low Gpiohs pin low
|
||||
* - GPIO_PV_High Gpiohs pin high
|
||||
*/
|
||||
gpio_pin_value_t gpiohs_get_pin(uint8_t pin);
|
||||
|
||||
/**
|
||||
* @brief Set Gpiohs pin value
|
||||
*
|
||||
* @param[in] pin Gpiohs pin
|
||||
* @param[in] value Gpiohs pin value
|
||||
*/
|
||||
void gpiohs_set_pin(uint8_t pin, gpio_pin_value_t value);
|
||||
|
||||
/**
|
||||
* @brief Set Gpiohs pin edge for interrupt
|
||||
*
|
||||
* @param[in] pin Gpiohs pin
|
||||
* @param[in] edge Gpiohs pin edge type
|
||||
*/
|
||||
void gpiohs_set_pin_edge(uint8_t pin, gpio_pin_edge_t edge);
|
||||
|
||||
/**
|
||||
* @brief Set Gpiohs pin interrupt
|
||||
*
|
||||
* @param[in] pin Gpiohs pin
|
||||
* @param[in] priority Gpiohs pin interrupt priority
|
||||
* @param[in] func Gpiohs pin interrupt service routine
|
||||
*/
|
||||
void gpiohs_set_irq(uint8_t pin, uint32_t priority, void(*func)());
|
||||
|
||||
/**
|
||||
* @brief Set Gpiohs pin interrupt
|
||||
*
|
||||
* @param[in] pin Gpiohs pin
|
||||
* @param[in] priority Gpiohs pin interrupt priority
|
||||
* @param[in] callback Gpiohs pin interrupt service routine
|
||||
* @param[in] ctx Gpiohs interrupt param
|
||||
*/
|
||||
void gpiohs_irq_register(uint8_t pin, uint32_t priority, plic_irq_callback_t callback, void *ctx);
|
||||
|
||||
/**
|
||||
* @brief Unregister Gpiohs pin interrupt
|
||||
*
|
||||
* @param[in] pin Gpiohs pin
|
||||
*/
|
||||
void gpiohs_irq_unregister(uint8_t pin);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _DRIVER_GPIOHS_H */
|
||||
|
||||
@@ -1,446 +0,0 @@
|
||||
/* Copyright 2018 Canaan Inc.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* http://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 _DRIVER_I2C_H
|
||||
#define _DRIVER_I2C_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include "dmac.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define I2C_MAX_NUM 3
|
||||
|
||||
/* clang-format off */
|
||||
typedef struct _i2c
|
||||
{
|
||||
/* I2C Control Register (0x00) */
|
||||
volatile uint32_t con;
|
||||
/* I2C Target Address Register (0x04) */
|
||||
volatile uint32_t tar;
|
||||
/* I2C Slave Address Register (0x08) */
|
||||
volatile uint32_t sar;
|
||||
/* reserved (0x0c) */
|
||||
volatile uint32_t resv1;
|
||||
/* I2C Data Buffer and Command Register (0x10) */
|
||||
volatile uint32_t data_cmd;
|
||||
/* I2C Standard Speed Clock SCL High Count Register (0x14) */
|
||||
volatile uint32_t ss_scl_hcnt;
|
||||
/* I2C Standard Speed Clock SCL Low Count Register (0x18) */
|
||||
volatile uint32_t ss_scl_lcnt;
|
||||
/* reserverd (0x1c-0x28) */
|
||||
volatile uint32_t resv2[4];
|
||||
/* I2C Interrupt Status Register (0x2c) */
|
||||
volatile uint32_t intr_stat;
|
||||
/* I2C Interrupt Mask Register (0x30) */
|
||||
volatile uint32_t intr_mask;
|
||||
/* I2C Raw Interrupt Status Register (0x34) */
|
||||
volatile uint32_t raw_intr_stat;
|
||||
/* I2C Receive FIFO Threshold Register (0x38) */
|
||||
volatile uint32_t rx_tl;
|
||||
/* I2C Transmit FIFO Threshold Register (0x3c) */
|
||||
volatile uint32_t tx_tl;
|
||||
/* I2C Clear Combined and Individual Interrupt Register (0x40) */
|
||||
volatile uint32_t clr_intr;
|
||||
/* I2C Clear RX_UNDER Interrupt Register (0x44) */
|
||||
volatile uint32_t clr_rx_under;
|
||||
/* I2C Clear RX_OVER Interrupt Register (0x48) */
|
||||
volatile uint32_t clr_rx_over;
|
||||
/* I2C Clear TX_OVER Interrupt Register (0x4c) */
|
||||
volatile uint32_t clr_tx_over;
|
||||
/* I2C Clear RD_REQ Interrupt Register (0x50) */
|
||||
volatile uint32_t clr_rd_req;
|
||||
/* I2C Clear TX_ABRT Interrupt Register (0x54) */
|
||||
volatile uint32_t clr_tx_abrt;
|
||||
/* I2C Clear RX_DONE Interrupt Register (0x58) */
|
||||
volatile uint32_t clr_rx_done;
|
||||
/* I2C Clear ACTIVITY Interrupt Register (0x5c) */
|
||||
volatile uint32_t clr_activity;
|
||||
/* I2C Clear STOP_DET Interrupt Register (0x60) */
|
||||
volatile uint32_t clr_stop_det;
|
||||
/* I2C Clear START_DET Interrupt Register (0x64) */
|
||||
volatile uint32_t clr_start_det;
|
||||
/* I2C Clear GEN_CALL Interrupt Register (0x68) */
|
||||
volatile uint32_t clr_gen_call;
|
||||
/* I2C Enable Register (0x6c) */
|
||||
volatile uint32_t enable;
|
||||
/* I2C Status Register (0x70) */
|
||||
volatile uint32_t status;
|
||||
/* I2C Transmit FIFO Level Register (0x74) */
|
||||
volatile uint32_t txflr;
|
||||
/* I2C Receive FIFO Level Register (0x78) */
|
||||
volatile uint32_t rxflr;
|
||||
/* I2C SDA Hold Time Length Register (0x7c) */
|
||||
volatile uint32_t sda_hold;
|
||||
/* I2C Transmit Abort Source Register (0x80) */
|
||||
volatile uint32_t tx_abrt_source;
|
||||
/* reserved (0x84) */
|
||||
volatile uint32_t resv3;
|
||||
/* I2C DMA Control Register (0x88) */
|
||||
volatile uint32_t dma_cr;
|
||||
/* I2C DMA Transmit Data Level Register (0x8c) */
|
||||
volatile uint32_t dma_tdlr;
|
||||
/* I2C DMA Receive Data Level Register (0x90) */
|
||||
volatile uint32_t dma_rdlr;
|
||||
/* I2C SDA Setup Register (0x94) */
|
||||
volatile uint32_t sda_setup;
|
||||
/* I2C ACK General Call Register (0x98) */
|
||||
volatile uint32_t general_call;
|
||||
/* I2C Enable Status Register (0x9c) */
|
||||
volatile uint32_t enable_status;
|
||||
/* I2C SS, FS or FM+ spike suppression limit (0xa0) */
|
||||
volatile uint32_t fs_spklen;
|
||||
/* reserved (0xa4-0xf0) */
|
||||
volatile uint32_t resv4[20];
|
||||
/* I2C Component Parameter Register 1 (0xf4) */
|
||||
volatile uint32_t comp_param_1;
|
||||
/* I2C Component Version Register (0xf8) */
|
||||
volatile uint32_t comp_version;
|
||||
/* I2C Component Type Register (0xfc) */
|
||||
volatile uint32_t comp_type;
|
||||
} __attribute__((packed, aligned(4))) i2c_t;
|
||||
|
||||
/* I2C Control Register*/
|
||||
#define I2C_CON_MASTER_MODE 0x00000001U
|
||||
#define I2C_CON_SPEED_MASK 0x00000006U
|
||||
#define I2C_CON_SPEED(x) ((x) << 1)
|
||||
#define I2C_CON_10BITADDR_SLAVE 0x00000008U
|
||||
#define I2C_CON_RESTART_EN 0x00000020U
|
||||
#define I2C_CON_SLAVE_DISABLE 0x00000040U
|
||||
#define I2C_CON_STOP_DET_IFADDRESSED 0x00000080U
|
||||
#define I2C_CON_TX_EMPTY_CTRL 0x00000100U
|
||||
|
||||
/* I2C Target Address Register*/
|
||||
#define I2C_TAR_ADDRESS_MASK 0x000003FFU
|
||||
#define I2C_TAR_ADDRESS(x) ((x) << 0)
|
||||
#define I2C_TAR_GC_OR_START 0x00000400U
|
||||
#define I2C_TAR_SPECIAL 0x00000800U
|
||||
#define I2C_TAR_10BITADDR_MASTER 0x00001000U
|
||||
|
||||
/* I2C Slave Address Register*/
|
||||
#define I2C_SAR_ADDRESS_MASK 0x000003FFU
|
||||
#define I2C_SAR_ADDRESS(x) ((x) << 0)
|
||||
|
||||
/* I2C Rx/Tx Data Buffer and Command Register*/
|
||||
#define I2C_DATA_CMD_CMD 0x00000100U
|
||||
#define I2C_DATA_CMD_DATA_MASK 0x000000FFU
|
||||
#define I2C_DATA_CMD_DATA(x) ((x) << 0)
|
||||
|
||||
/* Standard Speed I2C Clock SCL High Count Register*/
|
||||
#define I2C_SS_SCL_HCNT_COUNT_MASK 0x0000FFFFU
|
||||
#define I2C_SS_SCL_HCNT_COUNT(x) ((x) << 0)
|
||||
|
||||
/* Standard Speed I2C Clock SCL Low Count Register*/
|
||||
#define I2C_SS_SCL_LCNT_COUNT_MASK 0x0000FFFFU
|
||||
#define I2C_SS_SCL_LCNT_COUNT(x) ((x) << 0)
|
||||
|
||||
/* I2C Interrupt Status Register*/
|
||||
#define I2C_INTR_STAT_RX_UNDER 0x00000001U
|
||||
#define I2C_INTR_STAT_RX_OVER 0x00000002U
|
||||
#define I2C_INTR_STAT_RX_FULL 0x00000004U
|
||||
#define I2C_INTR_STAT_TX_OVER 0x00000008U
|
||||
#define I2C_INTR_STAT_TX_EMPTY 0x00000010U
|
||||
#define I2C_INTR_STAT_RD_REQ 0x00000020U
|
||||
#define I2C_INTR_STAT_TX_ABRT 0x00000040U
|
||||
#define I2C_INTR_STAT_RX_DONE 0x00000080U
|
||||
#define I2C_INTR_STAT_ACTIVITY 0x00000100U
|
||||
#define I2C_INTR_STAT_STOP_DET 0x00000200U
|
||||
#define I2C_INTR_STAT_START_DET 0x00000400U
|
||||
#define I2C_INTR_STAT_GEN_CALL 0x00000800U
|
||||
|
||||
/* I2C Interrupt Mask Register*/
|
||||
#define I2C_INTR_MASK_RX_UNDER 0x00000001U
|
||||
#define I2C_INTR_MASK_RX_OVER 0x00000002U
|
||||
#define I2C_INTR_MASK_RX_FULL 0x00000004U
|
||||
#define I2C_INTR_MASK_TX_OVER 0x00000008U
|
||||
#define I2C_INTR_MASK_TX_EMPTY 0x00000010U
|
||||
#define I2C_INTR_MASK_RD_REQ 0x00000020U
|
||||
#define I2C_INTR_MASK_TX_ABRT 0x00000040U
|
||||
#define I2C_INTR_MASK_RX_DONE 0x00000080U
|
||||
#define I2C_INTR_MASK_ACTIVITY 0x00000100U
|
||||
#define I2C_INTR_MASK_STOP_DET 0x00000200U
|
||||
#define I2C_INTR_MASK_START_DET 0x00000400U
|
||||
#define I2C_INTR_MASK_GEN_CALL 0x00000800U
|
||||
|
||||
/* I2C Raw Interrupt Status Register*/
|
||||
#define I2C_RAW_INTR_MASK_RX_UNDER 0x00000001U
|
||||
#define I2C_RAW_INTR_MASK_RX_OVER 0x00000002U
|
||||
#define I2C_RAW_INTR_MASK_RX_FULL 0x00000004U
|
||||
#define I2C_RAW_INTR_MASK_TX_OVER 0x00000008U
|
||||
#define I2C_RAW_INTR_MASK_TX_EMPTY 0x00000010U
|
||||
#define I2C_RAW_INTR_MASK_RD_REQ 0x00000020U
|
||||
#define I2C_RAW_INTR_MASK_TX_ABRT 0x00000040U
|
||||
#define I2C_RAW_INTR_MASK_RX_DONE 0x00000080U
|
||||
#define I2C_RAW_INTR_MASK_ACTIVITY 0x00000100U
|
||||
#define I2C_RAW_INTR_MASK_STOP_DET 0x00000200U
|
||||
#define I2C_RAW_INTR_MASK_START_DET 0x00000400U
|
||||
#define I2C_RAW_INTR_MASK_GEN_CALL 0x00000800U
|
||||
|
||||
/* I2C Receive FIFO Threshold Register*/
|
||||
#define I2C_RX_TL_VALUE_MASK 0x00000007U
|
||||
#define I2C_RX_TL_VALUE(x) ((x) << 0)
|
||||
|
||||
/* I2C Transmit FIFO Threshold Register*/
|
||||
#define I2C_TX_TL_VALUE_MASK 0x00000007U
|
||||
#define I2C_TX_TL_VALUE(x) ((x) << 0)
|
||||
|
||||
/* Clear Combined and Individual Interrupt Register*/
|
||||
#define I2C_CLR_INTR_CLR 0x00000001U
|
||||
|
||||
/* Clear RX_UNDER Interrupt Register*/
|
||||
#define I2C_CLR_RX_UNDER_CLR 0x00000001U
|
||||
|
||||
/* Clear RX_OVER Interrupt Register*/
|
||||
#define I2C_CLR_RX_OVER_CLR 0x00000001U
|
||||
|
||||
/* Clear TX_OVER Interrupt Register*/
|
||||
#define I2C_CLR_TX_OVER_CLR 0x00000001U
|
||||
|
||||
/* Clear RD_REQ Interrupt Register*/
|
||||
#define I2C_CLR_RD_REQ_CLR 0x00000001U
|
||||
|
||||
/* Clear TX_ABRT Interrupt Register*/
|
||||
#define I2C_CLR_TX_ABRT_CLR 0x00000001U
|
||||
|
||||
/* Clear RX_DONE Interrupt Register*/
|
||||
#define I2C_CLR_RX_DONE_CLR 0x00000001U
|
||||
|
||||
/* Clear ACTIVITY Interrupt Register*/
|
||||
#define I2C_CLR_ACTIVITY_CLR 0x00000001U
|
||||
|
||||
/* Clear STOP_DET Interrupt Register*/
|
||||
#define I2C_CLR_STOP_DET_CLR 0x00000001U
|
||||
|
||||
/* Clear START_DET Interrupt Register*/
|
||||
#define I2C_CLR_START_DET_CLR 0x00000001U
|
||||
|
||||
/* Clear GEN_CALL Interrupt Register*/
|
||||
#define I2C_CLR_GEN_CALL_CLR 0x00000001U
|
||||
|
||||
/* I2C Enable Register*/
|
||||
#define I2C_ENABLE_ENABLE 0x00000001U
|
||||
#define I2C_ENABLE_ABORT 0x00000002U
|
||||
#define I2C_ENABLE_TX_CMD_BLOCK 0x00000004U
|
||||
|
||||
/* I2C Status Register*/
|
||||
#define I2C_STATUS_ACTIVITY 0x00000001U
|
||||
#define I2C_STATUS_TFNF 0x00000002U
|
||||
#define I2C_STATUS_TFE 0x00000004U
|
||||
#define I2C_STATUS_RFNE 0x00000008U
|
||||
#define I2C_STATUS_RFF 0x00000010U
|
||||
#define I2C_STATUS_MST_ACTIVITY 0x00000020U
|
||||
#define I2C_STATUS_SLV_ACTIVITY 0x00000040U
|
||||
|
||||
/* I2C Transmit FIFO Level Register*/
|
||||
#define I2C_TXFLR_VALUE_MASK 0x00000007U
|
||||
#define I2C_TXFLR_VALUE(x) ((x) << 0)
|
||||
|
||||
/* I2C Receive FIFO Level Register*/
|
||||
#define I2C_RXFLR_VALUE_MASK 0x00000007U
|
||||
#define I2C_RXFLR_VALUE(x) ((x) << 0)
|
||||
|
||||
/* I2C SDA Hold Time Length Register*/
|
||||
#define I2C_SDA_HOLD_TX_MASK 0x0000FFFFU
|
||||
#define I2C_SDA_HOLD_TX(x) ((x) << 0)
|
||||
#define I2C_SDA_HOLD_RX_MASK 0x00FF0000U
|
||||
#define I2C_SDA_HOLD_RX(x) ((x) << 16)
|
||||
|
||||
/* I2C Transmit Abort Source Register*/
|
||||
#define I2C_TX_ABRT_SOURCE_7B_ADDR_NOACK 0x00000001U
|
||||
#define I2C_TX_ABRT_SOURCE_10B_ADDR1_NOACK 0x00000002U
|
||||
#define I2C_TX_ABRT_SOURCE_10B_ADDR2_NOACK 0x00000004U
|
||||
#define I2C_TX_ABRT_SOURCE_TXDATA_NOACK 0x00000008U
|
||||
#define I2C_TX_ABRT_SOURCE_GCALL_NOACK 0x00000010U
|
||||
#define I2C_TX_ABRT_SOURCE_GCALL_READ 0x00000020U
|
||||
#define I2C_TX_ABRT_SOURCE_HS_ACKDET 0x00000040U
|
||||
#define I2C_TX_ABRT_SOURCE_SBYTE_ACKDET 0x00000080U
|
||||
#define I2C_TX_ABRT_SOURCE_HS_NORSTRT 0x00000100U
|
||||
#define I2C_TX_ABRT_SOURCE_SBYTE_NORSTRT 0x00000200U
|
||||
#define I2C_TX_ABRT_SOURCE_10B_RD_NORSTRT 0x00000400U
|
||||
#define I2C_TX_ABRT_SOURCE_MASTER_DIS 0x00000800U
|
||||
#define I2C_TX_ABRT_SOURCE_MST_ARBLOST 0x00001000U
|
||||
#define I2C_TX_ABRT_SOURCE_SLVFLUSH_TXFIFO 0x00002000U
|
||||
#define I2C_TX_ABRT_SOURCE_SLV_ARBLOST 0x00004000U
|
||||
#define I2C_TX_ABRT_SOURCE_SLVRD_INTX 0x00008000U
|
||||
#define I2C_TX_ABRT_SOURCE_USER_ABRT 0x00010000U
|
||||
|
||||
/* DMA Control Register*/
|
||||
#define I2C_DMA_CR_RDMAE 0x00000001U
|
||||
#define I2C_DMA_CR_TDMAE 0x00000002U
|
||||
|
||||
/* DMA Transmit Data Level Register*/
|
||||
#define I2C_DMA_TDLR_VALUE_MASK 0x00000007U
|
||||
#define I2C_DMA_TDLR_VALUE(x) ((x) << 0)
|
||||
|
||||
/* DMA Receive Data Level Register*/
|
||||
#define I2C_DMA_RDLR_VALUE_MASK 0x00000007U
|
||||
#define I2C_DMA_RDLR_VALUE(x) ((x) << 0)
|
||||
|
||||
/* I2C SDA Setup Register*/
|
||||
#define I2C_SDA_SETUP_VALUE_MASK 0x000000FFU
|
||||
#define I2C_SDA_SETUP_VALUE(x) ((x) << 0)
|
||||
|
||||
/* I2C ACK General Call Register*/
|
||||
#define I2C_ACK_GENERAL_CALL_ENABLE 0x00000001U
|
||||
|
||||
/* I2C Enable Status Register*/
|
||||
#define I2C_ENABLE_STATUS_IC_ENABLE 0x00000001U
|
||||
#define I2C_ENABLE_STATUS_SLV_DIS_BUSY 0x00000002U
|
||||
#define I2C_ENABLE_STATUS_SLV_RX_DATA_LOST 0x00000004U
|
||||
|
||||
/* I2C SS, FS or FM+ spike suppression limit*/
|
||||
#define I2C_FS_SPKLEN_VALUE_MASK 0x000000FFU
|
||||
#define I2C_FS_SPKLEN_VALUE(x) ((x) << 0)
|
||||
|
||||
/* Component Parameter Register 1*/
|
||||
#define I2C_COMP_PARAM1_APB_DATA_WIDTH 0x00000003U
|
||||
#define I2C_COMP_PARAM1_MAX_SPEED_MODE 0x0000000CU
|
||||
#define I2C_COMP_PARAM1_HC_COUNT_VALUES 0x00000010U
|
||||
#define I2C_COMP_PARAM1_INTR_IO 0x00000020U
|
||||
#define I2C_COMP_PARAM1_HAS_DMA 0x00000040U
|
||||
#define I2C_COMP_PARAM1_ENCODED_PARAMS 0x00000080U
|
||||
#define I2C_COMP_PARAM1_RX_BUFFER_DEPTH 0x0000FF00U
|
||||
#define I2C_COMP_PARAM1_TX_BUFFER_DEPTH 0x00FF0000U
|
||||
|
||||
/* I2C Component Version Register*/
|
||||
#define I2C_COMP_VERSION_VALUE 0xFFFFFFFFU
|
||||
|
||||
/* I2C Component Type Register*/
|
||||
#define I2C_COMP_TYPE_VALUE 0xFFFFFFFFU
|
||||
/* clang-format on */
|
||||
|
||||
extern volatile i2c_t *const i2c[3];
|
||||
|
||||
typedef enum _i2c_device_number
|
||||
{
|
||||
I2C_DEVICE_0,
|
||||
I2C_DEVICE_1,
|
||||
I2C_DEVICE_2,
|
||||
I2C_DEVICE_MAX,
|
||||
} i2c_device_number_t;
|
||||
|
||||
typedef enum _i2c_bus_speed_mode
|
||||
{
|
||||
I2C_BS_STANDARD,
|
||||
I2C_BS_FAST,
|
||||
I2C_BS_HIGHSPEED
|
||||
} i2c_bus_speed_mode_t;
|
||||
|
||||
typedef enum _i2c_event
|
||||
{
|
||||
I2C_EV_START,
|
||||
I2C_EV_RESTART,
|
||||
I2C_EV_STOP
|
||||
} i2c_event_t;
|
||||
|
||||
typedef struct _i2c_slave_handler
|
||||
{
|
||||
void(*on_receive)(uint32_t data);
|
||||
uint32_t(*on_transmit)();
|
||||
void(*on_event)(i2c_event_t event);
|
||||
} i2c_slave_handler_t;
|
||||
|
||||
/**
|
||||
* @brief Set i2c params
|
||||
*
|
||||
* @param[in] i2c_num i2c number
|
||||
* @param[in] slave_address i2c slave device address
|
||||
* @param[in] address_width address width 7bit or 10bit
|
||||
* @param[in] i2c_clk i2c clk rate
|
||||
*/
|
||||
void i2c_init(i2c_device_number_t i2c_num, uint32_t slave_address, uint32_t address_width,
|
||||
uint32_t i2c_clk);
|
||||
|
||||
/**
|
||||
* @brief I2c send data
|
||||
*
|
||||
* @param[in] i2c_num i2c number
|
||||
* @param[in] send_buf send data
|
||||
* @param[in] send_buf_len send data length
|
||||
*
|
||||
* @return result
|
||||
* - 0 Success
|
||||
* - Other Fail
|
||||
*/
|
||||
int i2c_send_data(i2c_device_number_t i2c_num, const uint8_t *send_buf, size_t send_buf_len);
|
||||
|
||||
/**
|
||||
* @brief Init i2c as slave mode.
|
||||
*
|
||||
* @param[in] i2c_num i2c number
|
||||
* @param[in] slave_address i2c slave device address
|
||||
* @param[in] address_width address width 7bit or 10bit
|
||||
* @param[in] handler Handle of i2c slave interrupt function.
|
||||
*/
|
||||
void i2c_init_as_slave(i2c_device_number_t i2c_num, uint32_t slave_address, uint32_t address_width,
|
||||
const i2c_slave_handler_t *handler);
|
||||
|
||||
/**
|
||||
* @brief I2c send data by dma
|
||||
*
|
||||
* @param[in] dma_channel_num dma channel
|
||||
* @param[in] i2c_num i2c number
|
||||
* @param[in] send_buf send data
|
||||
* @param[in] send_buf_len send data length
|
||||
*
|
||||
* @return result
|
||||
* - 0 Success
|
||||
* - Other Fail
|
||||
*/
|
||||
void i2c_send_data_dma(dmac_channel_number_t dma_channel_num, i2c_device_number_t i2c_num, const uint8_t *send_buf,
|
||||
size_t send_buf_len);
|
||||
|
||||
/**
|
||||
* @brief I2c receive data
|
||||
*
|
||||
* @param[in] i2c_num i2c number
|
||||
* @param[in] send_buf send data address
|
||||
* @param[in] send_buf_len length of send buf
|
||||
* @param[in] receive_buf receive buf address
|
||||
* @param[in] receive_buf_len length of receive buf
|
||||
*
|
||||
* @return result
|
||||
* - 0 Success
|
||||
* - Other Fail
|
||||
*/
|
||||
int i2c_recv_data(i2c_device_number_t i2c_num, const uint8_t *send_buf, size_t send_buf_len, uint8_t *receive_buf,
|
||||
size_t receive_buf_len);
|
||||
|
||||
/**
|
||||
* @brief I2c receive data by dma
|
||||
*
|
||||
* @param[in] dma_send_channel_num send dma channel
|
||||
* @param[in] dma_receive_channel_num receive dma channel
|
||||
* @param[in] i2c_num i2c number
|
||||
* @param[in] send_buf send data address
|
||||
* @param[in] send_buf_len length of send buf
|
||||
* @param[in] receive_buf receive buf address
|
||||
* @param[in] receive_buf_len length of receive buf
|
||||
*
|
||||
* @return result
|
||||
* - 0 Success
|
||||
* - Other Fail
|
||||
*/
|
||||
void i2c_recv_data_dma(dmac_channel_number_t dma_send_channel_num, dmac_channel_number_t dma_receive_channel_num,
|
||||
i2c_device_number_t i2c_num, const uint8_t *send_buf, size_t send_buf_len,
|
||||
uint8_t *receive_buf, size_t receive_buf_len);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _DRIVER_I2C_H */
|
||||
@@ -1,753 +0,0 @@
|
||||
/* Copyright 2018 Canaan Inc.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* http://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 _DRIVER_I2S_H
|
||||
#define _DRIVER_I2S_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include "platform.h"
|
||||
#include "io.h"
|
||||
#include "dmac.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
#define I2S0_IN_D0 90
|
||||
#define I2S0_SCLK 88
|
||||
#define I2S0_WS 89
|
||||
|
||||
typedef enum _i2s_device_number
|
||||
{
|
||||
I2S_DEVICE_0 = 0,
|
||||
I2S_DEVICE_1 = 1,
|
||||
I2S_DEVICE_2 = 2,
|
||||
I2S_DEVICE_MAX
|
||||
} i2s_device_number_t;
|
||||
|
||||
typedef enum _i2s_channel_num
|
||||
{
|
||||
I2S_CHANNEL_0 = 0,
|
||||
I2S_CHANNEL_1 = 1,
|
||||
I2S_CHANNEL_2 = 2,
|
||||
I2S_CHANNEL_3 = 3
|
||||
} i2s_channel_num_t;
|
||||
|
||||
typedef enum _i2s_transmit
|
||||
{
|
||||
I2S_TRANSMITTER = 0,
|
||||
I2S_RECEIVER = 1
|
||||
} i2s_transmit_t;
|
||||
|
||||
typedef enum _i2s_work_mode
|
||||
{
|
||||
STANDARD_MODE = 1,
|
||||
RIGHT_JUSTIFYING_MODE = 2,
|
||||
LEFT_JUSTIFYING_MODE = 4
|
||||
} i2s_work_mode_t;
|
||||
|
||||
typedef enum _sclk_gating_cycles
|
||||
{
|
||||
/* Clock gating is diable */
|
||||
NO_CLOCK_GATING = 0x0,
|
||||
/* Gating after 12 sclk cycles */
|
||||
CLOCK_CYCLES_12 = 0x1,
|
||||
/* Gating after 16 sclk cycles */
|
||||
CLOCK_CYCLES_16 = 0x2,
|
||||
/* Gating after 20 sclk cycles */
|
||||
CLOCK_CYCLES_20 = 0x3,
|
||||
/* Gating after 24 sclk cycles */
|
||||
CLOCK_CYCLES_24 = 0x4
|
||||
} i2s_sclk_gating_cycles_t;
|
||||
|
||||
typedef enum _word_select_cycles
|
||||
{
|
||||
/* 16 sclk cycles */
|
||||
SCLK_CYCLES_16 = 0x0,
|
||||
/* 24 sclk cycles */
|
||||
SCLK_CYCLES_24 = 0x1,
|
||||
/* 32 sclk cycles */
|
||||
SCLK_CYCLES_32 = 0x2
|
||||
} i2s_word_select_cycles_t;
|
||||
|
||||
typedef enum _word_length
|
||||
{
|
||||
/* Ignore the word length */
|
||||
IGNORE_WORD_LENGTH = 0x0,
|
||||
/* 12-bit data resolution of the receiver */
|
||||
RESOLUTION_12_BIT = 0x1,
|
||||
/* 16-bit data resolution of the receiver */
|
||||
RESOLUTION_16_BIT = 0x2,
|
||||
/* 20-bit data resolution of the receiver */
|
||||
RESOLUTION_20_BIT = 0x3,
|
||||
/* 24-bit data resolution of the receiver */
|
||||
RESOLUTION_24_BIT = 0x4,
|
||||
/* 32-bit data resolution of the receiver */
|
||||
RESOLUTION_32_BIT = 0x5
|
||||
} i2s_word_length_t;
|
||||
|
||||
typedef enum _fifo_threshold
|
||||
{
|
||||
/* Interrupt trigger when FIFO level is 1 */
|
||||
TRIGGER_LEVEL_1 = 0x0,
|
||||
/* Interrupt trigger when FIFO level is 2 */
|
||||
TRIGGER_LEVEL_2 = 0x1,
|
||||
/* Interrupt trigger when FIFO level is 3 */
|
||||
TRIGGER_LEVEL_3 = 0x2,
|
||||
/* Interrupt trigger when FIFO level is 4 */
|
||||
TRIGGER_LEVEL_4 = 0x3,
|
||||
/* Interrupt trigger when FIFO level is 5 */
|
||||
TRIGGER_LEVEL_5 = 0x4,
|
||||
/* Interrupt trigger when FIFO level is 6 */
|
||||
TRIGGER_LEVEL_6 = 0x5,
|
||||
/* Interrupt trigger when FIFO level is 7 */
|
||||
TRIGGER_LEVEL_7 = 0x6,
|
||||
/* Interrupt trigger when FIFO level is 8 */
|
||||
TRIGGER_LEVEL_8 = 0x7,
|
||||
/* Interrupt trigger when FIFO level is 9 */
|
||||
TRIGGER_LEVEL_9 = 0x8,
|
||||
/* Interrupt trigger when FIFO level is 10 */
|
||||
TRIGGER_LEVEL_10 = 0x9,
|
||||
/* Interrupt trigger when FIFO level is 11 */
|
||||
TRIGGER_LEVEL_11 = 0xa,
|
||||
/* Interrupt trigger when FIFO level is 12 */
|
||||
TRIGGER_LEVEL_12 = 0xb,
|
||||
/* Interrupt trigger when FIFO level is 13 */
|
||||
TRIGGER_LEVEL_13 = 0xc,
|
||||
/* Interrupt trigger when FIFO level is 14 */
|
||||
TRIGGER_LEVEL_14 = 0xd,
|
||||
/* Interrupt trigger when FIFO level is 15 */
|
||||
TRIGGER_LEVEL_15 = 0xe,
|
||||
/* Interrupt trigger when FIFO level is 16 */
|
||||
TRIGGER_LEVEL_16 = 0xf
|
||||
} i2s_fifo_threshold_t;
|
||||
|
||||
|
||||
typedef struct _i2s_ier
|
||||
{
|
||||
/* Bit 0 is ien, 0 for disable i2s and 1 for enable i2s */
|
||||
uint32_t ien : 1;
|
||||
/* Bits [31:1] is reserved */
|
||||
uint32_t resv : 31;
|
||||
} __attribute__((packed, aligned(4))) i2s_ier_t;
|
||||
|
||||
typedef union _ier_u
|
||||
{
|
||||
i2s_ier_t ier;
|
||||
uint32_t reg_data;
|
||||
} ier_t;
|
||||
|
||||
typedef struct _i2s_irer
|
||||
{
|
||||
/* Bit 0 is receiver block enable,
|
||||
* 0 for receiver disable
|
||||
* 1 for receiver enable
|
||||
*/
|
||||
uint32_t rxen : 1;
|
||||
/* Bits [31:1] is reserved */
|
||||
uint32_t resv : 31;
|
||||
} __attribute__((packed, aligned(4))) i2s_irer_t;
|
||||
|
||||
typedef union _irer_u
|
||||
{
|
||||
i2s_irer_t irer;
|
||||
uint32_t reg_data;
|
||||
} irer_t;
|
||||
|
||||
typedef struct _i2s_iter
|
||||
{
|
||||
uint32_t txen : 1;
|
||||
/* Bit 0 is transmitter block enable,
|
||||
* 0 for transmitter disable
|
||||
* 1 for transmitter enable
|
||||
*/
|
||||
uint32_t resv : 31;
|
||||
/* Bits [31:1] is reserved */
|
||||
} __attribute__((packed, aligned(4))) i2s_iter_t;
|
||||
|
||||
typedef union _iter_u
|
||||
{
|
||||
i2s_iter_t iter;
|
||||
uint32_t reg_data;
|
||||
} iter_t;
|
||||
|
||||
typedef struct _i2s_cer
|
||||
{
|
||||
uint32_t clken : 1;
|
||||
/* Bit 0 is clock generation enable/disable,
|
||||
* 0 for clock generation disable,
|
||||
* 1 for clock generation enable
|
||||
*/
|
||||
uint32_t resv : 31;
|
||||
/* Bits [31:1] is reserved */
|
||||
} __attribute__((packed, aligned(4))) i2s_cer_t;
|
||||
|
||||
typedef union _cer_u
|
||||
{
|
||||
i2s_cer_t cer;
|
||||
uint32_t reg_data;
|
||||
} cer_t;
|
||||
|
||||
typedef struct _i2s_ccr
|
||||
{
|
||||
/* Bits [2:0] is used to program the gating of sclk,
|
||||
* 0x0 for clock gating is diable,
|
||||
* 0x1 for gating after 12 sclk cycles
|
||||
* 0x2 for gating after 16 sclk cycles
|
||||
* 0x3 for gating after 20 sclk cycles
|
||||
* 0x4 for gating after 24 sclk cycles
|
||||
*/
|
||||
uint32_t clk_gate : 3;
|
||||
/* Bits [4:3] used program the number of sclk cycles for which the
|
||||
* word select line stayd in the left aligned or right aligned mode.
|
||||
* 0x0 for 16sclk cycles, 0x1 for 24 sclk cycles 0x2 for 32 sclk
|
||||
* cycles
|
||||
*/
|
||||
uint32_t clk_word_size : 2;
|
||||
/* Bit[5:7] is alignment mode setting.
|
||||
* 0x1 for standard i2s format
|
||||
* 0x2 for right aligned format
|
||||
* 0x4 for left aligned format
|
||||
*/
|
||||
uint32_t align_mode : 3;
|
||||
/* Bit[8] is DMA transmit enable control */
|
||||
uint32_t dma_tx_en : 1;
|
||||
/* Bit[9] is DMA receive enable control */
|
||||
uint32_t dma_rx_en : 1;
|
||||
uint32_t dma_divide_16 : 1;
|
||||
/* Bit[10] split 32bit data to two 16 bit data and filled in left
|
||||
* and right channel. Used with dma_tx_en or dma_rx_en
|
||||
*/
|
||||
uint32_t sign_expand_en : 1;
|
||||
uint32_t resv : 20;
|
||||
/* Bits [31:11] is reseved */
|
||||
} __attribute__((packed, aligned(4))) i2s_ccr_t;
|
||||
|
||||
typedef union _ccr_u
|
||||
{
|
||||
i2s_ccr_t ccr;
|
||||
uint32_t reg_data;
|
||||
} ccr_t;
|
||||
|
||||
typedef struct _i2s_rxffr
|
||||
{
|
||||
uint32_t rxffr : 1;
|
||||
/* Bit 0 is receiver FIFO reset,
|
||||
* 0 for does not flush RX FIFO, 1 for flush RX FIFO
|
||||
*/
|
||||
uint32_t resv : 31;
|
||||
/* Bits [31:1] is reserved */
|
||||
} __attribute__((packed, aligned(4))) i2s_rxffr_t;
|
||||
|
||||
typedef union _rxffr_u
|
||||
{
|
||||
i2s_rxffr_t rxffr;
|
||||
uint32_t reg_data;
|
||||
} rxffr_t;
|
||||
|
||||
typedef struct _i2s_lrbrthr
|
||||
{
|
||||
uint32_t fifo : 16;
|
||||
/* Bits [15:0] if used data receive or transmit */
|
||||
uint32_t resv : 16;
|
||||
} i2s_lrbrthr_t;
|
||||
|
||||
typedef union _lrbthr_u
|
||||
{
|
||||
i2s_lrbrthr_t buffer;
|
||||
uint32_t reg_data;
|
||||
} lrbthr_t;
|
||||
|
||||
typedef struct _i2s_rthr
|
||||
{
|
||||
/* Bits [15:0] is right stereo data transmitted serially
|
||||
* from transmit channel input
|
||||
*/
|
||||
uint32_t rthrx : 16;
|
||||
/* Bits [31:16] is reserved */
|
||||
uint32_t resv : 16;
|
||||
} __attribute__((packed, aligned(4))) i2s_rthr_t;
|
||||
|
||||
typedef union _rthr_u
|
||||
{
|
||||
i2s_rthr_t rthr;
|
||||
uint32_t reg_data;
|
||||
} rthr_t;
|
||||
|
||||
typedef struct _i2s_rer
|
||||
{
|
||||
/* Bit 0 is receive channel enable/disable, 0 for receive channel disable,
|
||||
*1 for receive channel enable
|
||||
*/
|
||||
uint32_t rxchenx : 1;
|
||||
/* Bits [31:1] is reseved */
|
||||
uint32_t resv : 31;
|
||||
} __attribute__((packed, aligned(4))) i2s_rer_t;
|
||||
|
||||
typedef union _rer_u
|
||||
{
|
||||
i2s_rer_t rer;
|
||||
uint32_t reg_data;
|
||||
} rer_t;
|
||||
|
||||
typedef struct _i2s_ter
|
||||
{
|
||||
/* Bit 0 is transmit channel enable/disable, 0 for transmit channel disable,
|
||||
* 1 for transmit channel enable
|
||||
*/
|
||||
uint32_t txchenx : 1;
|
||||
/* Bits [31:1] is reseved */
|
||||
uint32_t resv : 31;
|
||||
} __attribute__((packed, aligned(4))) i2s_ter_t;
|
||||
|
||||
typedef union _ter_u
|
||||
{
|
||||
i2s_ter_t ter;
|
||||
uint32_t reg_data;
|
||||
} ter_t;
|
||||
|
||||
typedef struct _i2s_rcr_tcr
|
||||
{
|
||||
/* Bits [2:0] is used to program desired data resolution of
|
||||
* receiver/transmitter,
|
||||
* 0x0 for ignore the word length
|
||||
* 0x1 for 12-bit data resolution of the receiver/transmitter,
|
||||
* 0x2 for 16-bit data resolution of the receiver/transmitter,
|
||||
* 0x3 for 20-bit data resolution of the receiver/transmitter,
|
||||
* 0x4 for 24-bit data resolution of the receiver/transmitter,
|
||||
* 0x5 for 32-bit data resolution of the receiver/transmitter
|
||||
*/
|
||||
uint32_t wlen : 3;
|
||||
/* Bits [31:3] is reseved */
|
||||
uint32_t resv : 29;
|
||||
} __attribute__((packed, aligned(4))) i2s_rcr_tcr_t;
|
||||
|
||||
typedef union _rcr_tcr_u {
|
||||
i2s_rcr_tcr_t rcr_tcr;
|
||||
uint32_t reg_data;
|
||||
} rcr_tcr_t;
|
||||
|
||||
typedef struct _i2s_isr
|
||||
{
|
||||
/* Bit 0 is status of receiver data avaliable interrupt
|
||||
* 0x0 for RX FIFO trigger level not reached
|
||||
* 0x1 for RX FIFO trigger level is reached
|
||||
*/
|
||||
uint32_t rxda : 1;
|
||||
/* Bit 1 is status of data overrun interrupt for rx channel
|
||||
* 0x0 for RX FIFO write valid
|
||||
* 0x1 for RX FIFO write overrun
|
||||
*/
|
||||
uint32_t rxfo : 1;
|
||||
/* Bits [3:2] is reserved */
|
||||
uint32_t resv1 : 2;
|
||||
/* Bit 4 is status of transmit empty triger interrupt
|
||||
* 0x0 for TX FIFO triiger level is reach
|
||||
* 0x1 for TX FIFO trigger level is not reached
|
||||
*/
|
||||
uint32_t txfe : 1;
|
||||
/* BIt 5 is status of data overrun interrupt for the TX channel
|
||||
* 0x0 for TX FIFO write valid
|
||||
* 0x1 for TX FIFO write overrun
|
||||
*/
|
||||
uint32_t txfo : 1;
|
||||
/* BIts [31:6] is reserved */
|
||||
uint32_t resv2 : 26;
|
||||
} __attribute__((packed, aligned(4))) i2s_isr_t;
|
||||
|
||||
typedef union _isr_u
|
||||
{
|
||||
i2s_isr_t isr;
|
||||
uint32_t reg_data;
|
||||
} isr_t;
|
||||
|
||||
typedef struct _i2s_imr
|
||||
{
|
||||
/* Bit 0 is mask RX FIFO data available interrupt
|
||||
* 0x0 for unmask RX FIFO data available interrupt
|
||||
* 0x1 for mask RX FIFO data available interrupt
|
||||
*/
|
||||
uint32_t rxdam : 1;
|
||||
/* Bit 1 is mask RX FIFO overrun interrupt
|
||||
* 0x0 for unmask RX FIFO overrun interrupt
|
||||
* 0x1 for mask RX FIFO overrun interrupt
|
||||
*/
|
||||
uint32_t rxfom : 1;
|
||||
/* Bits [3:2] is reserved */
|
||||
uint32_t resv1 : 2;
|
||||
/* Bit 4 is mask TX FIFO empty interrupt,
|
||||
* 0x0 for unmask TX FIFO empty interrupt,
|
||||
* 0x1 for mask TX FIFO empty interrupt
|
||||
*/
|
||||
uint32_t txfem : 1;
|
||||
/* BIt 5 is mask TX FIFO overrun interrupt
|
||||
* 0x0 for mask TX FIFO overrun interrupt
|
||||
* 0x1 for unmash TX FIFO overrun interrupt
|
||||
*/
|
||||
uint32_t txfom : 1;
|
||||
/* Bits [31:6] is reserved */
|
||||
uint32_t resv2 : 26;
|
||||
} __attribute__((packed, aligned(4))) i2s_imr_t;
|
||||
|
||||
typedef union _imr_u
|
||||
{
|
||||
i2s_imr_t imr;
|
||||
uint32_t reg_data;
|
||||
} imr_t;
|
||||
|
||||
typedef struct _i2s_ror
|
||||
{
|
||||
/* Bit 0 is read this bit to clear RX FIFO data overrun interrupt
|
||||
* 0x0 for RX FIFO write valid,
|
||||
*0x1 for RX FIFO write overrun
|
||||
*/
|
||||
uint32_t rxcho : 1;
|
||||
/* Bits [31:1] is reserved */
|
||||
uint32_t resv : 31;
|
||||
} __attribute__((packed, aligned(4))) i2s_ror_t;
|
||||
|
||||
typedef union _ror_u
|
||||
{
|
||||
i2s_ror_t ror;
|
||||
uint32_t reg_data;
|
||||
} ror_t;
|
||||
|
||||
typedef struct _i2s_tor
|
||||
{
|
||||
/* Bit 0 is read this bit to clear TX FIFO data overrun interrupt
|
||||
* 0x0 for TX FIFO write valid,
|
||||
*0x1 for TX FIFO write overrun
|
||||
*/
|
||||
uint32_t txcho : 1;
|
||||
/* Bits [31:1] is reserved */
|
||||
uint32_t resv : 31;
|
||||
} __attribute__((packed, aligned(4))) i2s_tor_t;
|
||||
|
||||
typedef union _tor_u
|
||||
{
|
||||
i2s_tor_t tor;
|
||||
uint32_t reg_data;
|
||||
} tor_t;
|
||||
|
||||
typedef struct _i2s_rfcr
|
||||
{
|
||||
/* Bits [3:0] is used program the trigger level in the RX FIFO at
|
||||
* which the receiver data available interrupt generate,
|
||||
* 0x0 for interrupt trigger when FIFO level is 1,
|
||||
* 0x2 for interrupt trigger when FIFO level is 2,
|
||||
* 0x3 for interrupt trigger when FIFO level is 4,
|
||||
* 0x4 for interrupt trigger when FIFO level is 5,
|
||||
* 0x5 for interrupt trigger when FIFO level is 6,
|
||||
* 0x6 for interrupt trigger when FIFO level is 7,
|
||||
* 0x7 for interrupt trigger when FIFO level is 8,
|
||||
* 0x8 for interrupt trigger when FIFO level is 9,
|
||||
* 0x9 for interrupt trigger when FIFO level is 10,
|
||||
* 0xa for interrupt trigger when FIFO level is 11,
|
||||
* 0xb for interrupt trigger when FIFO level is 12,
|
||||
* 0xc for interrupt trigger when FIFO level is 13,
|
||||
* 0xd for interrupt trigger when FIFO level is 14,
|
||||
* 0xe for interrupt trigger when FIFO level is 15,
|
||||
* 0xf for interrupt trigger when FIFO level is 16
|
||||
*/
|
||||
uint32_t rxchdt : 4;
|
||||
/* Bits [31:4] is reserved */
|
||||
uint32_t rsvd_rfcrx : 28;
|
||||
} __attribute__((packed, aligned(4))) i2s_rfcr_t;
|
||||
|
||||
typedef union _rfcr_u
|
||||
{
|
||||
i2s_rfcr_t rfcr;
|
||||
uint32_t reg_data;
|
||||
} rfcr_t;
|
||||
|
||||
typedef struct _i2s_tfcr
|
||||
{
|
||||
/* Bits [3:0] is used program the trigger level in the TX FIFO at
|
||||
* which the receiver data available interrupt generate,
|
||||
* 0x0 for interrupt trigger when FIFO level is 1,
|
||||
* 0x2 for interrupt trigger when FIFO level is 2,
|
||||
* 0x3 for interrupt trigger when FIFO level is 4,
|
||||
* 0x4 for interrupt trigger when FIFO level is 5,
|
||||
* 0x5 for interrupt trigger when FIFO level is 6,
|
||||
* 0x6 for interrupt trigger when FIFO level is 7,
|
||||
* 0x7 for interrupt trigger when FIFO level is 8,
|
||||
* 0x8 for interrupt trigger when FIFO level is 9,
|
||||
* 0x9 for interrupt trigger when FIFO level is 10,
|
||||
* 0xa for interrupt trigger when FIFO level is 11,
|
||||
* 0xb for interrupt trigger when FIFO level is 12,
|
||||
* 0xc for interrupt trigger when FIFO level is 13,
|
||||
* 0xd for interrupt trigger when FIFO level is 14,
|
||||
* 0xe for interrupt trigger when FIFO level is 15,
|
||||
* 0xf for interrupt trigger when FIFO level is 16
|
||||
*/
|
||||
uint32_t txchet : 4;
|
||||
/* Bits [31:4] is reserved */
|
||||
uint32_t rsvd_tfcrx : 28;
|
||||
} __attribute__((packed, aligned(4))) i2s_tfcr_t;
|
||||
|
||||
typedef union _tfcr_u
|
||||
{
|
||||
i2s_tfcr_t tfcr;
|
||||
uint32_t reg_data;
|
||||
} tfcr_t;
|
||||
|
||||
typedef struct _i2s_rff
|
||||
{
|
||||
/* Bit 0 is receiver channel FIFO reset,
|
||||
* 0x0 for does not flush an individual RX FIFO,
|
||||
* 0x1 for flush an indiviadual RX FIFO
|
||||
*/
|
||||
uint32_t rxchfr : 1;
|
||||
/*< Bits [31:1] is reserved ,write only */
|
||||
uint32_t rsvd_rffx : 31;
|
||||
} __attribute__((packed, aligned(4))) i2s_rff_t;
|
||||
|
||||
typedef union _rff_u
|
||||
{
|
||||
i2s_rff_t rff;
|
||||
uint32_t reg_data;
|
||||
} rff_t;
|
||||
|
||||
typedef struct _i2s_tff
|
||||
{
|
||||
/* Bit 0 is transmit channel FIFO reset,
|
||||
* 0x0 for does not flush an individual TX FIFO,
|
||||
* 0x1 for flush an indiviadual TX FIFO
|
||||
*/
|
||||
uint32_t rtxchfr : 1;
|
||||
/*< Bits [31:1] is reserved ,write only */
|
||||
uint32_t rsvd_rffx : 31;
|
||||
} __attribute__((packed, aligned(4))) i2s_tff_t;
|
||||
|
||||
typedef union tff_u
|
||||
{
|
||||
i2s_tff_t tff;
|
||||
uint32_t reg_data;
|
||||
} tff_t;
|
||||
|
||||
typedef struct _i2s_channel
|
||||
{
|
||||
/* Left Receive or Left Transmit Register (0x20) */
|
||||
volatile uint32_t left_rxtx;
|
||||
/* Right Receive or Right Transmit Register (0x24) */
|
||||
volatile uint32_t right_rxtx;
|
||||
/* Receive Enable Register (0x28) */
|
||||
volatile uint32_t rer;
|
||||
/* Transmit Enable Register (0x2c) */
|
||||
volatile uint32_t ter;
|
||||
/* Receive Configuration Register (0x30) */
|
||||
volatile uint32_t rcr;
|
||||
/* Transmit Configuration Register (0x34) */
|
||||
volatile uint32_t tcr;
|
||||
/* Interrupt Status Register (0x38) */
|
||||
volatile uint32_t isr;
|
||||
/* Interrupt Mask Register (0x3c) */
|
||||
volatile uint32_t imr;
|
||||
/* Receive Overrun Register (0x40) */
|
||||
volatile uint32_t ror;
|
||||
/* Transmit Overrun Register (0x44) */
|
||||
volatile uint32_t tor;
|
||||
/* Receive FIFO Configuration Register (0x48) */
|
||||
volatile uint32_t rfcr;
|
||||
/* Transmit FIFO Configuration Register (0x4c) */
|
||||
volatile uint32_t tfcr;
|
||||
/* Receive FIFO Flush Register (0x50) */
|
||||
volatile uint32_t rff;
|
||||
/* Transmit FIFO Flush Register (0x54) */
|
||||
volatile uint32_t tff;
|
||||
/* reserved (0x58-0x5c) */
|
||||
volatile uint32_t reserved1[2];
|
||||
} __attribute__((packed, aligned(4))) i2s_channel_t;
|
||||
|
||||
/****is* i2s.api/dw_i2s_portmap
|
||||
* NAME
|
||||
* i2s_t
|
||||
* DESCRIPTION
|
||||
* This is the structure used for accessing the i2s register
|
||||
* portmap.
|
||||
* EXAMPLE
|
||||
* struct i2s_t *portmap;
|
||||
* portmap = (struct dw_i2s_portmap *) DW_APB_I2S_BASE;
|
||||
* SOURCE
|
||||
*/
|
||||
typedef struct _i2s
|
||||
{
|
||||
/* I2S Enable Register (0x00) */
|
||||
volatile uint32_t ier;
|
||||
/* I2S Receiver Block Enable Register (0x04) */
|
||||
volatile uint32_t irer;
|
||||
/* I2S Transmitter Block Enable Register (0x08) */
|
||||
volatile uint32_t iter;
|
||||
/* Clock Enable Register (0x0c) */
|
||||
volatile uint32_t cer;
|
||||
/* Clock Configuration Register (0x10) */
|
||||
volatile uint32_t ccr;
|
||||
/* Receiver Block FIFO Reset Register (0x04) */
|
||||
volatile uint32_t rxffr;
|
||||
/* Transmitter Block FIFO Reset Register (0x18) */
|
||||
volatile uint32_t txffr;
|
||||
/* reserved (0x1c) */
|
||||
volatile uint32_t reserved1;
|
||||
volatile i2s_channel_t channel[4];
|
||||
/* reserved (0x118-0x1bc) */
|
||||
volatile uint32_t reserved2[40];
|
||||
/* Receiver Block DMA Register (0x1c0) */
|
||||
volatile uint32_t rxdma;
|
||||
/* Reset Receiver Block DMA Register (0x1c4) */
|
||||
volatile uint32_t rrxdma;
|
||||
/* Transmitter Block DMA Register (0x1c8) */
|
||||
volatile uint32_t txdma;
|
||||
/* Reset Transmitter Block DMA Register (0x1cc) */
|
||||
volatile uint32_t rtxdma;
|
||||
/* reserved (0x1d0-0x1ec) */
|
||||
volatile uint32_t reserved3[8];
|
||||
/* Component Parameter Register 2 (0x1f0) */
|
||||
volatile uint32_t i2s_comp_param_2;
|
||||
/* Component Parameter Register 1 (0x1f4) */
|
||||
volatile uint32_t i2s_comp_param_1;
|
||||
/* I2S Component Version Register (0x1f8) */
|
||||
volatile uint32_t i2s_comp_version_1;
|
||||
/* I2S Component Type Register (0x1fc) */
|
||||
volatile uint32_t i2s_comp_type;
|
||||
} __attribute__((packed, aligned(4))) i2s_t;
|
||||
|
||||
/**
|
||||
* @brief I2S object instance
|
||||
*/
|
||||
extern volatile i2s_t *const i2s[3];
|
||||
|
||||
/**
|
||||
* @brief I2s init
|
||||
*
|
||||
* @param[in] device_num The device number
|
||||
* @param[in] rxtx_mode I2s work mode
|
||||
* @param[in] channel_mask Channel mask to which channel work
|
||||
*
|
||||
*/
|
||||
void i2s_init(i2s_device_number_t device_num, i2s_transmit_t rxtx_mode, uint32_t channel_mask);
|
||||
|
||||
/**
|
||||
* @brief Read pcm data from dma
|
||||
*
|
||||
* @param[in] device_num which of device
|
||||
* @param[in] buf save read data
|
||||
* @param[in] buf_len the length to read form i2s
|
||||
* @param[in] channel_num The dma channel number
|
||||
*
|
||||
* @return result
|
||||
* - 0 Success
|
||||
* - Other Fail
|
||||
*/
|
||||
void i2s_receive_data_dma(i2s_device_number_t device_num, uint32_t *buf, size_t buf_len,
|
||||
dmac_channel_number_t channel_num);
|
||||
|
||||
/**
|
||||
* @brief Write pcm data to channel_num channel by dma, first wait dmac done
|
||||
*
|
||||
* @param[in] device_num which of device
|
||||
* @param[in] pcm Send data
|
||||
* @param[in] buf_len Send data length
|
||||
* @param[in] channel_num dmac channel
|
||||
*
|
||||
*/
|
||||
void i2s_send_data_dma(i2s_device_number_t device_num, const void *buf, size_t buf_len, dmac_channel_number_t channel_num);
|
||||
|
||||
/**
|
||||
* @brief I2S receive channel configure
|
||||
*
|
||||
* @param[in] device_num The device number
|
||||
* @param[in] channel_num The channel number
|
||||
* @param[in] word_length The word length
|
||||
* @param[in] word_select_size The word select size
|
||||
* @param[in] trigger_level The trigger level
|
||||
*/
|
||||
void i2s_rx_channel_config(i2s_device_number_t device_num,
|
||||
i2s_channel_num_t channel_num,
|
||||
i2s_word_length_t word_length,
|
||||
i2s_word_select_cycles_t word_select_size,
|
||||
i2s_fifo_threshold_t trigger_level,
|
||||
i2s_work_mode_t word_mode);
|
||||
|
||||
/**
|
||||
* @brief I2S transmit channel enable
|
||||
*
|
||||
* @param[in] device_num The device number
|
||||
* @param[in] channel_num The channel number
|
||||
* @param[in] word_length The word length
|
||||
* @param[in] word_select_size The word select size
|
||||
* @param[in] trigger_level The trigger level
|
||||
*/
|
||||
void i2s_tx_channel_config(i2s_device_number_t device_num,
|
||||
i2s_channel_num_t channel_num,
|
||||
i2s_word_length_t word_length,
|
||||
i2s_word_select_cycles_t word_select_size,
|
||||
i2s_fifo_threshold_t trigger_level,
|
||||
i2s_work_mode_t word_mode);
|
||||
|
||||
/**
|
||||
* @brief Play PCM format audio
|
||||
*
|
||||
* @param[in] device_num The device number
|
||||
* @param[in] channel_num The channel number
|
||||
* @param[in] buf PCM data
|
||||
* @param[in] buf_len PCM data length
|
||||
* @param[in] frame Transmit amount once
|
||||
* @param[in] bits_per_sample Sample bit length
|
||||
* @param[in] track_num Track amount
|
||||
*/
|
||||
void i2s_play(i2s_device_number_t device_num, dmac_channel_number_t channel_num,
|
||||
const uint8_t *buf, size_t buf_len, size_t frame, size_t bits_per_sample, uint8_t track_num);
|
||||
|
||||
/**
|
||||
* @brief Play PCM format audio
|
||||
*
|
||||
* @param[in] device_num The device number
|
||||
* @param[in] sample_rate The Sample rate
|
||||
*
|
||||
*
|
||||
* @return The real sample rate
|
||||
*/
|
||||
uint32_t i2s_set_sample_rate(i2s_device_number_t device_num, uint32_t sample_rate);
|
||||
|
||||
/**
|
||||
* @brief Set dma_divide_16 split 32bit data to two 16 bit data and filled in left
|
||||
* and right channel. Used with dma_tx_en or dma_rx_en
|
||||
*
|
||||
* @param[in] device_num The device number
|
||||
* @param[in] enable The value of dma_divide_16 0:disable 1:enable
|
||||
*
|
||||
* @return result
|
||||
* - 0 Success
|
||||
* - Other Fail
|
||||
*/
|
||||
int i2s_set_dma_divide_16(i2s_device_number_t device_num, uint32_t enable);
|
||||
|
||||
/**
|
||||
* @brief Get dma_divide_16.
|
||||
*
|
||||
* @param[in] device_num The device number
|
||||
*
|
||||
* @return result
|
||||
* - <0 Fail
|
||||
* - other value of dma_divide_16
|
||||
*/
|
||||
int i2s_get_dma_divide_16(i2s_device_number_t device_num);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -1,50 +0,0 @@
|
||||
/* Copyright 2018 Canaan Inc.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* http://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 _DRIVER_IO_H
|
||||
#define _DRIVER_IO_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define readb(addr) (*(volatile uint8_t *)(addr))
|
||||
#define readw(addr) (*(volatile uint16_t *)(addr))
|
||||
#define readl(addr) (*(volatile uint32_t *)(addr))
|
||||
#define readq(addr) (*(volatile uint64_t *)(addr))
|
||||
|
||||
#define writeb(v, addr) \
|
||||
{ \
|
||||
(*(volatile uint8_t *)(addr)) = (v); \
|
||||
}
|
||||
#define writew(v, addr) \
|
||||
{ \
|
||||
(*(volatile uint16_t *)(addr)) = (v); \
|
||||
}
|
||||
#define writel(v, addr) \
|
||||
{ \
|
||||
(*(volatile uint32_t *)(addr)) = (v); \
|
||||
}
|
||||
#define writeq(v, addr) \
|
||||
{ \
|
||||
(*(volatile uint64_t *)(addr)) = (v); \
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _DRIVER_IO_H */
|
||||
@@ -1,848 +0,0 @@
|
||||
#ifndef _KPU_H
|
||||
#define _KPU_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <plic.h>
|
||||
#include "dmac.h"
|
||||
|
||||
#define kpu_matmul_begin kpu_conv2d_output
|
||||
|
||||
typedef int (*plic_irq_callback_t)(void *ctx);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
union
|
||||
{
|
||||
uint64_t reg;
|
||||
struct
|
||||
{
|
||||
uint64_t int_en:1;
|
||||
uint64_t ram_flag:1;
|
||||
uint64_t full_add:1;
|
||||
uint64_t depth_wise_layer:1;
|
||||
uint64_t reserved:60;
|
||||
} data;
|
||||
} interrupt_enabe;
|
||||
|
||||
union
|
||||
{
|
||||
uint64_t reg;
|
||||
struct
|
||||
{
|
||||
uint64_t image_src_addr:15;
|
||||
uint64_t reserved0:17;
|
||||
uint64_t image_dst_addr:15;
|
||||
uint64_t reserved1:17;
|
||||
} data;
|
||||
} image_addr;
|
||||
|
||||
union
|
||||
{
|
||||
uint64_t reg;
|
||||
struct
|
||||
{
|
||||
uint64_t i_ch_num:10;
|
||||
uint64_t reserved0:22;
|
||||
uint64_t o_ch_num:10;
|
||||
uint64_t reserved1:6;
|
||||
uint64_t o_ch_num_coef:10;
|
||||
uint64_t reserved2:6;
|
||||
} data;
|
||||
} image_channel_num;
|
||||
|
||||
union
|
||||
{
|
||||
uint64_t reg;
|
||||
struct
|
||||
{
|
||||
uint64_t i_row_wid:10;
|
||||
uint64_t i_col_high:9;
|
||||
uint64_t reserved0:13;
|
||||
uint64_t o_row_wid:10;
|
||||
uint64_t o_col_high:9;
|
||||
uint64_t reserved1:13;
|
||||
} data;
|
||||
} image_size;
|
||||
|
||||
union
|
||||
{
|
||||
uint64_t reg;
|
||||
struct
|
||||
{
|
||||
uint64_t kernel_type:3;
|
||||
uint64_t pad_type:1;
|
||||
uint64_t pool_type:4;
|
||||
uint64_t first_stride:1;
|
||||
uint64_t bypass_conv:1;
|
||||
uint64_t load_para:1;
|
||||
uint64_t reserved0:5;
|
||||
uint64_t dma_burst_size:8;
|
||||
uint64_t pad_value:8;
|
||||
uint64_t bwsx_base_addr:32;
|
||||
} data;
|
||||
} kernel_pool_type_cfg;
|
||||
|
||||
union
|
||||
{
|
||||
uint64_t reg;
|
||||
struct
|
||||
{
|
||||
uint64_t load_coor:1;
|
||||
uint64_t load_time:6;
|
||||
uint64_t reserved0:8;
|
||||
uint64_t para_size:17;
|
||||
uint64_t para_start_addr:32;
|
||||
} data;
|
||||
} kernel_load_cfg;
|
||||
|
||||
union
|
||||
{
|
||||
uint64_t reg;
|
||||
struct
|
||||
{
|
||||
uint64_t coef_column_offset:4;
|
||||
uint64_t coef_row_offset:12;
|
||||
uint64_t reserved0:48;
|
||||
} data;
|
||||
} kernel_offset;
|
||||
|
||||
union
|
||||
{
|
||||
uint64_t reg;
|
||||
struct
|
||||
{
|
||||
uint64_t channel_switch_addr:15;
|
||||
uint64_t reserved:1;
|
||||
uint64_t row_switch_addr:4;
|
||||
uint64_t coef_size:8;
|
||||
uint64_t coef_group:3;
|
||||
uint64_t load_act:1;
|
||||
uint64_t active_addr:32;
|
||||
} data;
|
||||
} kernel_calc_type_cfg;
|
||||
|
||||
union
|
||||
{
|
||||
uint64_t reg;
|
||||
struct
|
||||
{
|
||||
uint64_t wb_channel_switch_addr:15;
|
||||
uint64_t reserved0:1;
|
||||
uint64_t wb_row_switch_addr:4;
|
||||
uint64_t wb_group:3;
|
||||
uint64_t reserved1:41;
|
||||
} data;
|
||||
} write_back_cfg;
|
||||
|
||||
union
|
||||
{
|
||||
uint64_t reg;
|
||||
struct
|
||||
{
|
||||
uint64_t shr_w:4;
|
||||
uint64_t shr_x:4;
|
||||
uint64_t arg_w:24;
|
||||
uint64_t arg_x:24;
|
||||
uint64_t reserved0:8;
|
||||
} data;
|
||||
} conv_value;
|
||||
|
||||
union
|
||||
{
|
||||
uint64_t reg;
|
||||
struct
|
||||
{
|
||||
uint64_t arg_add:40;
|
||||
uint64_t reserved:24;
|
||||
} data;
|
||||
} conv_value2;
|
||||
|
||||
union
|
||||
{
|
||||
uint64_t reg;
|
||||
struct
|
||||
{
|
||||
uint64_t send_data_out:1;
|
||||
uint64_t reserved:15;
|
||||
uint64_t channel_byte_num:16;
|
||||
uint64_t dma_total_byte:32;
|
||||
} data;
|
||||
} dma_parameter;
|
||||
} kpu_layer_argument_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
union
|
||||
{
|
||||
uint64_t reg;
|
||||
struct
|
||||
{
|
||||
uint64_t shift_number:8;
|
||||
uint64_t y_mul:16;
|
||||
uint64_t x_start:36;
|
||||
} data;
|
||||
} activate_para[16];
|
||||
|
||||
union
|
||||
{
|
||||
uint64_t reg;
|
||||
struct
|
||||
{
|
||||
uint8_t result_bias[8];
|
||||
} data;
|
||||
} activate_para_bias0;
|
||||
|
||||
union
|
||||
{
|
||||
uint64_t reg;
|
||||
struct
|
||||
{
|
||||
uint8_t result_bias[8];
|
||||
} data;
|
||||
} activate_para_bias1;
|
||||
} kpu_activate_table_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
union
|
||||
{
|
||||
uint64_t reg;
|
||||
struct
|
||||
{
|
||||
uint64_t norm_mul:24;
|
||||
uint64_t norm_add:32;
|
||||
uint64_t norm_shift:4;
|
||||
} data;
|
||||
} batchnorm;
|
||||
} kpu_batchnorm_argument_t;
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
union
|
||||
{
|
||||
uint64_t reg;
|
||||
struct
|
||||
{
|
||||
uint16_t weight[9];
|
||||
} data;
|
||||
} weights;
|
||||
} kpu_weights_kernel_16_3x3_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint64_t calc_done_int:1;
|
||||
uint64_t layer_cfg_almost_empty_int:1;
|
||||
uint64_t layer_cfg_almost_full_int:1;
|
||||
uint64_t reserved:61;
|
||||
} kpu_config_interrupt_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint64_t fifo_full_threshold:4;
|
||||
uint64_t fifo_empty_threshold:4;
|
||||
uint64_t reserved:56;
|
||||
} kpu_config_fifo_threshold_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint64_t dma_fifo_flush_n:1;
|
||||
uint64_t gs_fifo_flush_n:1;
|
||||
uint64_t cfg_fifo_flush_n:1;
|
||||
uint64_t cmd_fifo_flush_n:1;
|
||||
uint64_t resp_fifo_flush_n:1;
|
||||
uint64_t reserved:59;
|
||||
} kpu_config_fifo_ctrl_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint64_t eight_bit_mode:1;
|
||||
uint64_t reserved:63;
|
||||
} kpu_config_eight_bit_mode_t;
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
volatile uint64_t layer_argument_fifo;
|
||||
|
||||
volatile union
|
||||
{
|
||||
uint64_t reg;
|
||||
kpu_config_interrupt_t data;
|
||||
} interrupt_status;
|
||||
|
||||
volatile union
|
||||
{
|
||||
uint64_t reg;
|
||||
kpu_config_interrupt_t data;
|
||||
} interrupt_raw;
|
||||
|
||||
volatile union {
|
||||
uint64_t reg;
|
||||
kpu_config_interrupt_t data;
|
||||
} interrupt_mask;
|
||||
|
||||
volatile union
|
||||
{
|
||||
uint64_t reg;
|
||||
kpu_config_interrupt_t data;
|
||||
} interrupt_clear;
|
||||
|
||||
volatile union
|
||||
{
|
||||
uint64_t reg;
|
||||
kpu_config_fifo_threshold_t data;
|
||||
} fifo_threshold;
|
||||
|
||||
volatile uint64_t fifo_data_out;
|
||||
|
||||
volatile union
|
||||
{
|
||||
uint64_t reg;
|
||||
kpu_config_fifo_ctrl_t data;
|
||||
} fifo_ctrl;
|
||||
|
||||
volatile union
|
||||
{
|
||||
uint64_t reg;
|
||||
kpu_config_eight_bit_mode_t data;
|
||||
} eight_bit_mode;
|
||||
} kpu_config_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
kpu_layer_argument_t *layers;
|
||||
kpu_layer_argument_t *remain_layers;
|
||||
plic_irq_callback_t callback;
|
||||
void *ctx;
|
||||
uint64_t *src;
|
||||
uint64_t *dst;
|
||||
uint32_t src_length;
|
||||
uint32_t dst_length;
|
||||
uint32_t layers_length;
|
||||
uint32_t remain_layers_length;
|
||||
dmac_channel_number_t dma_ch;
|
||||
uint32_t eight_bit_mode;
|
||||
float output_scale;
|
||||
float output_bias;
|
||||
float input_scale;
|
||||
float input_bias;
|
||||
} kpu_task_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32_t version;
|
||||
uint32_t flags;
|
||||
uint32_t arch;
|
||||
uint32_t layers_length;
|
||||
uint32_t max_start_address;
|
||||
uint32_t main_mem_usage;
|
||||
uint32_t output_count;
|
||||
} kpu_kmodel_header_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32_t version;
|
||||
uint32_t flags;
|
||||
uint32_t layers_length;
|
||||
uint32_t max_start_address;
|
||||
uint32_t layers_argument_start;
|
||||
} kpu_model_header_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32_t address;
|
||||
uint32_t size;
|
||||
} kpu_model_output_t;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
KL_INVALID = 0,
|
||||
KL_ADD,
|
||||
KL_QUANTIZED_ADD,
|
||||
KL_GLOBAL_MAX_POOL2D,
|
||||
KL_QUANTIZED_GLOBAL_MAX_POOL2D,
|
||||
KL_GLOBAL_AVERAGE_POOL2D,
|
||||
KL_QUANTIZED_GLOBAL_AVERAGE_POOL2D,
|
||||
KL_MAX_POOL2D,
|
||||
KL_QUANTIZED_MAX_POOL2D,
|
||||
KL_AVERAGE_POOL2D,
|
||||
KL_QUANTIZED_AVERAGE_POOL2D,
|
||||
KL_QUANTIZE,
|
||||
KL_DEQUANTIZE,
|
||||
KL_REQUANTIZE,
|
||||
KL_L2_NORMALIZATION,
|
||||
KL_SOFTMAX,
|
||||
KL_CONCAT,
|
||||
KL_QUANTIZED_CONCAT,
|
||||
KL_FULLY_CONNECTED,
|
||||
KL_QUANTIZED_FULLY_CONNECTED,
|
||||
KL_TENSORFLOW_FLATTEN,
|
||||
KL_QUANTIZED_TENSORFLOW_FLATTEN,
|
||||
KL_K210_CONV = 10240,
|
||||
KL_K210_ADD_PADDING,
|
||||
KL_K210_REMOVE_PADDING,
|
||||
KL_K210_UPLOAD
|
||||
} kpu_model_layer_type_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32_t type;
|
||||
uint32_t body_size;
|
||||
} kpu_model_layer_header_t;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
KLF_NONE = 0,
|
||||
KLF_MAIN_MEM_OUT = 1
|
||||
} kpu_model_layer_flags_t;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
KLP_SAME = 0,
|
||||
KLP_VALID = 1
|
||||
} kpu_model_padding_t;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
KLA_LINEAR = 0,
|
||||
KLA_RELU = 1,
|
||||
KLA_RELU6 = 2
|
||||
} kpu_model_activation_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float scale;
|
||||
float bias;
|
||||
} kpu_model_quant_param_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32_t width;
|
||||
uint32_t height;
|
||||
uint32_t channels;
|
||||
} kpu_model_shape_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32_t start;
|
||||
uint32_t size;
|
||||
} kpu_model_memory_range_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32_t flags;
|
||||
uint32_t main_mem_out_address;
|
||||
uint32_t layer_offset;
|
||||
uint32_t weights_offset;
|
||||
uint32_t bn_offset;
|
||||
uint32_t act_offset;
|
||||
} kpu_model_conv_layer_argument_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32_t flags;
|
||||
uint32_t main_mem_in_a_address;
|
||||
uint32_t main_mem_in_b_address;
|
||||
uint32_t main_mem_out_address;
|
||||
uint32_t count;
|
||||
} kpu_model_add_layer_argument_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32_t flags;
|
||||
uint32_t main_mem_in_a_address;
|
||||
uint32_t main_mem_in_b_address;
|
||||
uint32_t main_mem_out_address;
|
||||
uint32_t count;
|
||||
int32_t in_a_offset;
|
||||
int32_t in_a_mul;
|
||||
int32_t in_a_shift;
|
||||
int32_t in_b_offset;
|
||||
int32_t in_b_mul;
|
||||
int32_t in_b_shift;
|
||||
int32_t out_offset;
|
||||
int32_t out_mul;
|
||||
int32_t out_shift;
|
||||
} kpu_model_quant_add_layer_argument_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32_t flags;
|
||||
uint32_t main_mem_in_address;
|
||||
uint32_t main_mem_out_address;
|
||||
uint32_t kernel_size;
|
||||
uint32_t channels;
|
||||
} kpu_model_gap2d_layer_argument_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32_t flags;
|
||||
uint32_t main_mem_in_address;
|
||||
uint32_t main_mem_out_address;
|
||||
kpu_model_shape_t in_shape;
|
||||
kpu_model_shape_t out_shape;
|
||||
uint32_t kernel_width;
|
||||
uint32_t kernel_height;
|
||||
uint32_t stride_width;
|
||||
uint32_t stride_height;
|
||||
uint32_t padding_width;
|
||||
uint32_t padding_height;
|
||||
} kpu_model_quant_max_pool2d_layer_argument_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32_t flags;
|
||||
uint32_t main_mem_in_address;
|
||||
uint32_t main_mem_out_address;
|
||||
kpu_model_shape_t in_shape;
|
||||
kpu_model_shape_t out_shape;
|
||||
uint32_t kernel_width;
|
||||
uint32_t kernel_height;
|
||||
uint32_t stride_width;
|
||||
uint32_t stride_height;
|
||||
uint32_t padding_width;
|
||||
uint32_t padding_height;
|
||||
kpu_model_activation_t act;
|
||||
} kpu_model_ave_pool2d_layer_argument_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32_t flags;
|
||||
uint32_t main_mem_in_address;
|
||||
uint32_t mem_out_address;
|
||||
uint32_t count;
|
||||
kpu_model_quant_param_t quant_param;
|
||||
} kpu_model_quantize_layer_argument_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32_t flags;
|
||||
uint32_t main_mem_in_address;
|
||||
uint32_t main_mem_out_address;
|
||||
uint32_t count;
|
||||
kpu_model_quant_param_t quant_param;
|
||||
} kpu_model_dequantize_layer_argument_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32_t flags;
|
||||
uint32_t main_mem_in_address;
|
||||
uint32_t main_mem_out_address;
|
||||
uint32_t count;
|
||||
uint8_t table[256];
|
||||
} kpu_model_requantize_layer_argument_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32_t flags;
|
||||
uint32_t main_mem_in_address;
|
||||
uint32_t kpu_mem_out_address;
|
||||
uint32_t channels;
|
||||
} kpu_model_add_padding_layer_argument_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32_t flags;
|
||||
uint32_t main_mem_in_address;
|
||||
uint32_t main_mem_out_address;
|
||||
uint32_t channels;
|
||||
} kpu_model_remove_padding_layer_argument_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32_t flags;
|
||||
uint32_t main_mem_in_address;
|
||||
uint32_t kpu_mem_out_address;
|
||||
uint32_t width;
|
||||
uint32_t height;
|
||||
uint32_t channels;
|
||||
} kpu_model_upload_layer_argument_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32_t flags;
|
||||
uint32_t main_mem_in_address;
|
||||
uint32_t main_mem_out_address;
|
||||
uint32_t channels;
|
||||
} kpu_model_l2_norm_layer_argument_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32_t flags;
|
||||
uint32_t main_mem_in_address;
|
||||
uint32_t main_mem_out_address;
|
||||
uint32_t channels;
|
||||
} kpu_model_softmax_layer_argument_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32_t flags;
|
||||
uint32_t main_mem_out_address;
|
||||
uint32_t input_count;
|
||||
kpu_model_memory_range_t inputs_mem[0];
|
||||
} kpu_model_concat_layer_argument_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32_t flags;
|
||||
uint32_t main_mem_in_address;
|
||||
uint32_t main_mem_out_address;
|
||||
uint32_t in_channels;
|
||||
uint32_t out_channels;
|
||||
kpu_model_activation_t act;
|
||||
float weights[0];
|
||||
} kpu_model_fully_connected_layer_argument_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32_t flags;
|
||||
uint32_t main_mem_in_address;
|
||||
uint32_t main_mem_out_address;
|
||||
kpu_model_shape_t shape;
|
||||
} kpu_model_tf_flatten_layer_argument_t;
|
||||
|
||||
typedef void(*kpu_done_callback_t)(void* userdata);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
const uint8_t *model_buffer;
|
||||
uint8_t *main_buffer;
|
||||
uint32_t output_count;
|
||||
const kpu_model_output_t *outputs;
|
||||
const kpu_model_layer_header_t *layer_headers;
|
||||
const uint8_t *body_start;
|
||||
uint32_t layers_length;
|
||||
volatile uint32_t current_layer;
|
||||
const uint8_t * volatile current_body;
|
||||
dmac_channel_number_t dma_ch;
|
||||
kpu_done_callback_t done_callback;
|
||||
void *userdata;
|
||||
} kpu_model_context_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32_t weigths_offset;
|
||||
uint32_t bn_offset;
|
||||
uint32_t act_offset;
|
||||
float input_scale;
|
||||
float input_bias;
|
||||
float output_scale;
|
||||
float output_bias;
|
||||
} kpu_model_layer_metadata_t;
|
||||
|
||||
typedef struct _quantize_param
|
||||
{
|
||||
float scale;
|
||||
float bias;
|
||||
} quantize_param_t;
|
||||
|
||||
extern volatile kpu_config_t *const kpu;
|
||||
|
||||
/**
|
||||
* @brief Modle complier init kpu handler
|
||||
*
|
||||
* @param[in] task Kpu handler
|
||||
*
|
||||
* @return Kpu handler
|
||||
*/
|
||||
extern kpu_task_t *kpu_task_init(kpu_task_t* task);
|
||||
|
||||
/**
|
||||
* @brief Kpu run for AI
|
||||
*
|
||||
* @param[in] task Kpu handler
|
||||
* @param[in] dma_ch DMA for kpu
|
||||
* @param[in] src The picture data
|
||||
* @param[in] dest The result of kpu
|
||||
* @param[in] callback The callback of kpu
|
||||
*
|
||||
* @return result
|
||||
* - 0 Success
|
||||
* - Other Fail.Kpu is busy.
|
||||
*/
|
||||
int kpu_run(kpu_task_t* task, dmac_channel_number_t dma_ch, const void *src, void* dest, plic_irq_callback_t callback);
|
||||
|
||||
/**
|
||||
* @brief Get kpu result buf
|
||||
*
|
||||
* @param[in] task Kpu handler
|
||||
*
|
||||
* @return Kpu result buf
|
||||
*/
|
||||
uint8_t *kpu_get_output_buf(kpu_task_t* task);
|
||||
|
||||
/**
|
||||
* @brief Release kpu output buf
|
||||
*
|
||||
* @param[in] output_buf Kpu output buf
|
||||
*
|
||||
*/
|
||||
void kpu_release_output_buf(uint8_t *output_buf);
|
||||
|
||||
/**
|
||||
* @brief Kpu run for AI
|
||||
*
|
||||
* @param[in] task Kpu handler
|
||||
*
|
||||
* @return result
|
||||
* - 0 Success
|
||||
* - Other Fail.Kpu is busy.
|
||||
*/
|
||||
int kpu_start(kpu_task_t *task);
|
||||
|
||||
/**
|
||||
* @brief Initialize kpu handler
|
||||
*
|
||||
* @param[in] task Kpu handler
|
||||
*
|
||||
* @return result
|
||||
* - 0 Success
|
||||
* - Other Fail.
|
||||
*/
|
||||
int kpu_single_task_init(kpu_task_t *task);
|
||||
|
||||
/**
|
||||
* @brief Uninitialize kpu handler
|
||||
*
|
||||
* @param[in] task Kpu handler
|
||||
*
|
||||
* @return result
|
||||
* - 0 Success
|
||||
* - Other Fail.
|
||||
*/
|
||||
int kpu_single_task_deinit(kpu_task_t *task);
|
||||
|
||||
/**
|
||||
* @brief Load kmodel and init kpu task
|
||||
*
|
||||
* @param[in] task Kpu handler
|
||||
* @param[in] buffer Kmodel
|
||||
* @param[in] meta Test data
|
||||
*
|
||||
* @return result
|
||||
* - 0 Success
|
||||
* - Other Fail.
|
||||
*/
|
||||
int kpu_model_load_from_buffer(kpu_task_t *task, uint8_t *buffer, kpu_model_layer_metadata_t **meta);
|
||||
|
||||
/**
|
||||
* @brief Kpu initialize
|
||||
*
|
||||
* @param[in] eight_bit_mode 0:16bit mode 1:8bit mode
|
||||
* @param[in] callback Callback of kpu
|
||||
* @param[in] userdata Data of callback
|
||||
*
|
||||
*/
|
||||
void kpu_init(int eight_bit_mode, plic_irq_callback_t callback, void *userdata);
|
||||
|
||||
/**
|
||||
* @brief Kpu input data by dma
|
||||
*
|
||||
* @param[in] layer Kpu task layer
|
||||
* @param[in] src Image data
|
||||
* @param[in] dma_ch Dmac channel
|
||||
* @param[in] callback Dmac complete callback
|
||||
* @param[in] userdata Data of callback
|
||||
*
|
||||
*/
|
||||
void kpu_input_dma(const kpu_layer_argument_t *layer, const uint8_t *src, dmac_channel_number_t dma_ch, plic_irq_callback_t callback, void *userdata);
|
||||
|
||||
/**
|
||||
* @brief Kpu input data by cpu
|
||||
*
|
||||
* @param[in] layer Kpu task layer
|
||||
* @param[in] src Image data
|
||||
* @param[in] width Image width
|
||||
* @param[in] height Image heigth
|
||||
* @param[in] channels Color channel, RGB is 3
|
||||
*
|
||||
*/
|
||||
void kpu_input_with_padding(kpu_layer_argument_t *layer, const uint8_t *src, int width, int height, int channels);
|
||||
|
||||
/**
|
||||
* @brief Kpu run only one layer
|
||||
*
|
||||
* @param[in] layer Kpu task layer
|
||||
*
|
||||
*/
|
||||
void kpu_conv2d(kpu_layer_argument_t *layer);
|
||||
|
||||
/**
|
||||
* @brief Kpu run only one layer then get the result by dma
|
||||
*
|
||||
* @param[in] layer Kpu task layer
|
||||
* @param[in] dma_ch Dmac channel
|
||||
* @param[in] dest Result
|
||||
* @param[in] callback Dmac complete callback
|
||||
* @param[in] userdata Data of callback
|
||||
*
|
||||
*/
|
||||
void kpu_conv2d_output(kpu_layer_argument_t *layer, dmac_channel_number_t dma_ch, uint8_t *dest, plic_irq_callback_t callback, void *userdata);
|
||||
|
||||
/**
|
||||
* @brief Kpu pooling
|
||||
*
|
||||
* @param[in] src Source
|
||||
* @param[in] src_param Source param
|
||||
* @param[in] kernel_size Kernel size, 7*7 is 49
|
||||
* @param[in] channels Channels
|
||||
* @param[in] dest Dest
|
||||
* @param[in] dest_param Dest param
|
||||
*
|
||||
*/
|
||||
void kpu_global_average_pool(const uint8_t *src, const quantize_param_t *src_param, int kernel_size, int channels, uint8_t *dest, const quantize_param_t *dest_param);
|
||||
|
||||
/**
|
||||
* @brief Kpu pooling
|
||||
*
|
||||
* @param[in] src Source
|
||||
* @param[in] src_param Source param
|
||||
* @param[in] kernel_size Kernel size, 7*7 is 49
|
||||
* @param[in] channels Channels
|
||||
* @param[in] dest Dest
|
||||
*
|
||||
*/
|
||||
void kpu_global_average_pool_float(const uint8_t *src, const quantize_param_t *src_param, int kernel_size, int channels, float *dest);
|
||||
|
||||
/**
|
||||
* @brief Kpu fullly connected by cpu
|
||||
*
|
||||
* @param[in] src Source
|
||||
* @param[in] weights Weight
|
||||
* @param[in] biases Biases
|
||||
* @param[in] dest Dest
|
||||
* @param[in] input_channels Input channels
|
||||
* @param[in] output_channels Output channels
|
||||
*
|
||||
*/
|
||||
void kpu_fully_connected(const float *src, const float *weights, const float *biases, float *dest, int input_channels, int output_channels);
|
||||
|
||||
/**
|
||||
* @brief Kpu matrix multiplication
|
||||
*
|
||||
* @param[in] src Source
|
||||
* @param[in] channels Channels
|
||||
* @param[in] dest Dest
|
||||
* @param[in] dest_param Dest param
|
||||
*
|
||||
*/
|
||||
void kpu_matmul_end(const uint8_t *src, int channels, float *dest, const quantize_param_t *dest_param);
|
||||
|
||||
/**
|
||||
* @brief Kpu dequantize
|
||||
*
|
||||
* @param[in] src Source
|
||||
* @param[in] src_param Source param
|
||||
* @param[in] count Dequantize count
|
||||
* @param[in] dest Dest
|
||||
*
|
||||
*/
|
||||
void kpu_dequantize(const uint8_t *src, const quantize_param_t *src_param, size_t count, float *dest);
|
||||
|
||||
int kpu_load_kmodel(kpu_model_context_t *ctx, const uint8_t *buffer);
|
||||
void kpu_model_free(kpu_model_context_t *ctx);
|
||||
int kpu_get_output(kpu_model_context_t *ctx, uint32_t index, uint8_t **data, size_t *size);
|
||||
int kpu_run_kmodel(kpu_model_context_t *ctx, const uint8_t *src, dmac_channel_number_t dma_ch, kpu_done_callback_t done_callback, void *userdata);
|
||||
|
||||
#endif
|
||||
@@ -1,492 +0,0 @@
|
||||
/* Copyright 2018 Canaan Inc.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* http://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.
|
||||
*/
|
||||
/**
|
||||
* @file
|
||||
* @brief The PLIC complies with the RISC-V Privileged Architecture
|
||||
* specification, and can support a maximum of 1023 external
|
||||
* interrupt sources targeting up to 15,872 core contexts.
|
||||
*
|
||||
* @note PLIC RAM Layout
|
||||
*
|
||||
* | Address | Description |
|
||||
* |-----------|---------------------------------|
|
||||
* |0x0C000000 | Reserved |
|
||||
* |0x0C000004 | source 1 priority |
|
||||
* |0x0C000008 | source 2 priority |
|
||||
* |... | ... |
|
||||
* |0x0C000FFC | source 1023 priority |
|
||||
* | | |
|
||||
* |0x0C001000 | Start of pending array |
|
||||
* |... | (read-only) |
|
||||
* |0x0C00107C | End of pending array |
|
||||
* |0x0C001080 | Reserved |
|
||||
* |... | ... |
|
||||
* |0x0C001FFF | Reserved |
|
||||
* | | |
|
||||
* |0x0C002000 | target 0 enables |
|
||||
* |0x0C002080 | target 1 enables |
|
||||
* |... | ... |
|
||||
* |0x0C1F1F80 | target 15871 enables |
|
||||
* |0x0C1F2000 | Reserved |
|
||||
* |... | ... |
|
||||
* |0x0C1FFFFC | Reserved |
|
||||
* | | |
|
||||
* |0x0C200000 | target 0 priority threshold |
|
||||
* |0x0C200004 | target 0 claim/complete |
|
||||
* |... | ... |
|
||||
* |0x0C201000 | target 1 priority threshold |
|
||||
* |0x0C201004 | target 1 claim/complete |
|
||||
* |... | ... |
|
||||
* |0x0FFFF000 | target 15871 priority threshold |
|
||||
* |0x0FFFF004 | target 15871 claim/complete |
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _DRIVER_PLIC_H
|
||||
#define _DRIVER_PLIC_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include "encoding.h"
|
||||
#include "platform.h"
|
||||
|
||||
/* For c++ compatibility */
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* clang-format off */
|
||||
/* IRQ number settings */
|
||||
#define PLIC_NUM_SOURCES (IRQN_MAX - 1)
|
||||
#define PLIC_NUM_PRIORITIES (7)
|
||||
|
||||
/* Real number of cores */
|
||||
#define PLIC_NUM_CORES (2)
|
||||
/* clang-format on */
|
||||
|
||||
/**
|
||||
* @brief PLIC External Interrupt Numbers
|
||||
*
|
||||
* @note PLIC interrupt sources
|
||||
*
|
||||
* | Source | Name | Description |
|
||||
* |--------|--------------------------|------------------------------------|
|
||||
* | 0 | IRQN_NO_INTERRUPT | The non-existent interrupt |
|
||||
* | 1 | IRQN_SPI0_INTERRUPT | SPI0 interrupt |
|
||||
* | 2 | IRQN_SPI1_INTERRUPT | SPI1 interrupt |
|
||||
* | 3 | IRQN_SPI_SLAVE_INTERRUPT | SPI_SLAVE interrupt |
|
||||
* | 4 | IRQN_SPI3_INTERRUPT | SPI3 interrupt |
|
||||
* | 5 | IRQN_I2S0_INTERRUPT | I2S0 interrupt |
|
||||
* | 6 | IRQN_I2S1_INTERRUPT | I2S1 interrupt |
|
||||
* | 7 | IRQN_I2S2_INTERRUPT | I2S2 interrupt |
|
||||
* | 8 | IRQN_I2C0_INTERRUPT | I2C0 interrupt |
|
||||
* | 9 | IRQN_I2C1_INTERRUPT | I2C1 interrupt |
|
||||
* | 10 | IRQN_I2C2_INTERRUPT | I2C2 interrupt |
|
||||
* | 11 | IRQN_UART1_INTERRUPT | UART1 interrupt |
|
||||
* | 12 | IRQN_UART2_INTERRUPT | UART2 interrupt |
|
||||
* | 13 | IRQN_UART3_INTERRUPT | UART3 interrupt |
|
||||
* | 14 | IRQN_TIMER0A_INTERRUPT | TIMER0 channel 0 or 1 interrupt |
|
||||
* | 15 | IRQN_TIMER0B_INTERRUPT | TIMER0 channel 2 or 3 interrupt |
|
||||
* | 16 | IRQN_TIMER1A_INTERRUPT | TIMER1 channel 0 or 1 interrupt |
|
||||
* | 17 | IRQN_TIMER1B_INTERRUPT | TIMER1 channel 2 or 3 interrupt |
|
||||
* | 18 | IRQN_TIMER2A_INTERRUPT | TIMER2 channel 0 or 1 interrupt |
|
||||
* | 19 | IRQN_TIMER2B_INTERRUPT | TIMER2 channel 2 or 3 interrupt |
|
||||
* | 20 | IRQN_RTC_INTERRUPT | RTC tick and alarm interrupt |
|
||||
* | 21 | IRQN_WDT0_INTERRUPT | Watching dog timer0 interrupt |
|
||||
* | 22 | IRQN_WDT1_INTERRUPT | Watching dog timer1 interrupt |
|
||||
* | 23 | IRQN_APB_GPIO_INTERRUPT | APB GPIO interrupt |
|
||||
* | 24 | IRQN_DVP_INTERRUPT | Digital video port interrupt |
|
||||
* | 25 | IRQN_AI_INTERRUPT | AI accelerator interrupt |
|
||||
* | 26 | IRQN_FFT_INTERRUPT | FFT accelerator interrupt |
|
||||
* | 27 | IRQN_DMA0_INTERRUPT | DMA channel0 interrupt |
|
||||
* | 28 | IRQN_DMA1_INTERRUPT | DMA channel1 interrupt |
|
||||
* | 29 | IRQN_DMA2_INTERRUPT | DMA channel2 interrupt |
|
||||
* | 30 | IRQN_DMA3_INTERRUPT | DMA channel3 interrupt |
|
||||
* | 31 | IRQN_DMA4_INTERRUPT | DMA channel4 interrupt |
|
||||
* | 32 | IRQN_DMA5_INTERRUPT | DMA channel5 interrupt |
|
||||
* | 33 | IRQN_UARTHS_INTERRUPT | Hi-speed UART0 interrupt |
|
||||
* | 34 | IRQN_GPIOHS0_INTERRUPT | Hi-speed GPIO0 interrupt |
|
||||
* | 35 | IRQN_GPIOHS1_INTERRUPT | Hi-speed GPIO1 interrupt |
|
||||
* | 36 | IRQN_GPIOHS2_INTERRUPT | Hi-speed GPIO2 interrupt |
|
||||
* | 37 | IRQN_GPIOHS3_INTERRUPT | Hi-speed GPIO3 interrupt |
|
||||
* | 38 | IRQN_GPIOHS4_INTERRUPT | Hi-speed GPIO4 interrupt |
|
||||
* | 39 | IRQN_GPIOHS5_INTERRUPT | Hi-speed GPIO5 interrupt |
|
||||
* | 40 | IRQN_GPIOHS6_INTERRUPT | Hi-speed GPIO6 interrupt |
|
||||
* | 41 | IRQN_GPIOHS7_INTERRUPT | Hi-speed GPIO7 interrupt |
|
||||
* | 42 | IRQN_GPIOHS8_INTERRUPT | Hi-speed GPIO8 interrupt |
|
||||
* | 43 | IRQN_GPIOHS9_INTERRUPT | Hi-speed GPIO9 interrupt |
|
||||
* | 44 | IRQN_GPIOHS10_INTERRUPT | Hi-speed GPIO10 interrupt |
|
||||
* | 45 | IRQN_GPIOHS11_INTERRUPT | Hi-speed GPIO11 interrupt |
|
||||
* | 46 | IRQN_GPIOHS12_INTERRUPT | Hi-speed GPIO12 interrupt |
|
||||
* | 47 | IRQN_GPIOHS13_INTERRUPT | Hi-speed GPIO13 interrupt |
|
||||
* | 48 | IRQN_GPIOHS14_INTERRUPT | Hi-speed GPIO14 interrupt |
|
||||
* | 49 | IRQN_GPIOHS15_INTERRUPT | Hi-speed GPIO15 interrupt |
|
||||
* | 50 | IRQN_GPIOHS16_INTERRUPT | Hi-speed GPIO16 interrupt |
|
||||
* | 51 | IRQN_GPIOHS17_INTERRUPT | Hi-speed GPIO17 interrupt |
|
||||
* | 52 | IRQN_GPIOHS18_INTERRUPT | Hi-speed GPIO18 interrupt |
|
||||
* | 53 | IRQN_GPIOHS19_INTERRUPT | Hi-speed GPIO19 interrupt |
|
||||
* | 54 | IRQN_GPIOHS20_INTERRUPT | Hi-speed GPIO20 interrupt |
|
||||
* | 55 | IRQN_GPIOHS21_INTERRUPT | Hi-speed GPIO21 interrupt |
|
||||
* | 56 | IRQN_GPIOHS22_INTERRUPT | Hi-speed GPIO22 interrupt |
|
||||
* | 57 | IRQN_GPIOHS23_INTERRUPT | Hi-speed GPIO23 interrupt |
|
||||
* | 58 | IRQN_GPIOHS24_INTERRUPT | Hi-speed GPIO24 interrupt |
|
||||
* | 59 | IRQN_GPIOHS25_INTERRUPT | Hi-speed GPIO25 interrupt |
|
||||
* | 60 | IRQN_GPIOHS26_INTERRUPT | Hi-speed GPIO26 interrupt |
|
||||
* | 61 | IRQN_GPIOHS27_INTERRUPT | Hi-speed GPIO27 interrupt |
|
||||
* | 62 | IRQN_GPIOHS28_INTERRUPT | Hi-speed GPIO28 interrupt |
|
||||
* | 63 | IRQN_GPIOHS29_INTERRUPT | Hi-speed GPIO29 interrupt |
|
||||
* | 64 | IRQN_GPIOHS30_INTERRUPT | Hi-speed GPIO30 interrupt |
|
||||
* | 65 | IRQN_GPIOHS31_INTERRUPT | Hi-speed GPIO31 interrupt |
|
||||
*
|
||||
*/
|
||||
/* clang-format off */
|
||||
typedef enum _plic_irq
|
||||
{
|
||||
IRQN_NO_INTERRUPT = 0, /*!< The non-existent interrupt */
|
||||
IRQN_SPI0_INTERRUPT = 1, /*!< SPI0 interrupt */
|
||||
IRQN_SPI1_INTERRUPT = 2, /*!< SPI1 interrupt */
|
||||
IRQN_SPI_SLAVE_INTERRUPT = 3, /*!< SPI_SLAVE interrupt */
|
||||
IRQN_SPI3_INTERRUPT = 4, /*!< SPI3 interrupt */
|
||||
IRQN_I2S0_INTERRUPT = 5, /*!< I2S0 interrupt */
|
||||
IRQN_I2S1_INTERRUPT = 6, /*!< I2S1 interrupt */
|
||||
IRQN_I2S2_INTERRUPT = 7, /*!< I2S2 interrupt */
|
||||
IRQN_I2C0_INTERRUPT = 8, /*!< I2C0 interrupt */
|
||||
IRQN_I2C1_INTERRUPT = 9, /*!< I2C1 interrupt */
|
||||
IRQN_I2C2_INTERRUPT = 10, /*!< I2C2 interrupt */
|
||||
IRQN_UART1_INTERRUPT = 11, /*!< UART1 interrupt */
|
||||
IRQN_UART2_INTERRUPT = 12, /*!< UART2 interrupt */
|
||||
IRQN_UART3_INTERRUPT = 13, /*!< UART3 interrupt */
|
||||
IRQN_TIMER0A_INTERRUPT = 14, /*!< TIMER0 channel 0 or 1 interrupt */
|
||||
IRQN_TIMER0B_INTERRUPT = 15, /*!< TIMER0 channel 2 or 3 interrupt */
|
||||
IRQN_TIMER1A_INTERRUPT = 16, /*!< TIMER1 channel 0 or 1 interrupt */
|
||||
IRQN_TIMER1B_INTERRUPT = 17, /*!< TIMER1 channel 2 or 3 interrupt */
|
||||
IRQN_TIMER2A_INTERRUPT = 18, /*!< TIMER2 channel 0 or 1 interrupt */
|
||||
IRQN_TIMER2B_INTERRUPT = 19, /*!< TIMER2 channel 2 or 3 interrupt */
|
||||
IRQN_RTC_INTERRUPT = 20, /*!< RTC tick and alarm interrupt */
|
||||
IRQN_WDT0_INTERRUPT = 21, /*!< Watching dog timer0 interrupt */
|
||||
IRQN_WDT1_INTERRUPT = 22, /*!< Watching dog timer1 interrupt */
|
||||
IRQN_APB_GPIO_INTERRUPT = 23, /*!< APB GPIO interrupt */
|
||||
IRQN_DVP_INTERRUPT = 24, /*!< Digital video port interrupt */
|
||||
IRQN_AI_INTERRUPT = 25, /*!< AI accelerator interrupt */
|
||||
IRQN_FFT_INTERRUPT = 26, /*!< FFT accelerator interrupt */
|
||||
IRQN_DMA0_INTERRUPT = 27, /*!< DMA channel0 interrupt */
|
||||
IRQN_DMA1_INTERRUPT = 28, /*!< DMA channel1 interrupt */
|
||||
IRQN_DMA2_INTERRUPT = 29, /*!< DMA channel2 interrupt */
|
||||
IRQN_DMA3_INTERRUPT = 30, /*!< DMA channel3 interrupt */
|
||||
IRQN_DMA4_INTERRUPT = 31, /*!< DMA channel4 interrupt */
|
||||
IRQN_DMA5_INTERRUPT = 32, /*!< DMA channel5 interrupt */
|
||||
IRQN_UARTHS_INTERRUPT = 33, /*!< Hi-speed UART0 interrupt */
|
||||
IRQN_GPIOHS0_INTERRUPT = 34, /*!< Hi-speed GPIO0 interrupt */
|
||||
IRQN_GPIOHS1_INTERRUPT = 35, /*!< Hi-speed GPIO1 interrupt */
|
||||
IRQN_GPIOHS2_INTERRUPT = 36, /*!< Hi-speed GPIO2 interrupt */
|
||||
IRQN_GPIOHS3_INTERRUPT = 37, /*!< Hi-speed GPIO3 interrupt */
|
||||
IRQN_GPIOHS4_INTERRUPT = 38, /*!< Hi-speed GPIO4 interrupt */
|
||||
IRQN_GPIOHS5_INTERRUPT = 39, /*!< Hi-speed GPIO5 interrupt */
|
||||
IRQN_GPIOHS6_INTERRUPT = 40, /*!< Hi-speed GPIO6 interrupt */
|
||||
IRQN_GPIOHS7_INTERRUPT = 41, /*!< Hi-speed GPIO7 interrupt */
|
||||
IRQN_GPIOHS8_INTERRUPT = 42, /*!< Hi-speed GPIO8 interrupt */
|
||||
IRQN_GPIOHS9_INTERRUPT = 43, /*!< Hi-speed GPIO9 interrupt */
|
||||
IRQN_GPIOHS10_INTERRUPT = 44, /*!< Hi-speed GPIO10 interrupt */
|
||||
IRQN_GPIOHS11_INTERRUPT = 45, /*!< Hi-speed GPIO11 interrupt */
|
||||
IRQN_GPIOHS12_INTERRUPT = 46, /*!< Hi-speed GPIO12 interrupt */
|
||||
IRQN_GPIOHS13_INTERRUPT = 47, /*!< Hi-speed GPIO13 interrupt */
|
||||
IRQN_GPIOHS14_INTERRUPT = 48, /*!< Hi-speed GPIO14 interrupt */
|
||||
IRQN_GPIOHS15_INTERRUPT = 49, /*!< Hi-speed GPIO15 interrupt */
|
||||
IRQN_GPIOHS16_INTERRUPT = 50, /*!< Hi-speed GPIO16 interrupt */
|
||||
IRQN_GPIOHS17_INTERRUPT = 51, /*!< Hi-speed GPIO17 interrupt */
|
||||
IRQN_GPIOHS18_INTERRUPT = 52, /*!< Hi-speed GPIO18 interrupt */
|
||||
IRQN_GPIOHS19_INTERRUPT = 53, /*!< Hi-speed GPIO19 interrupt */
|
||||
IRQN_GPIOHS20_INTERRUPT = 54, /*!< Hi-speed GPIO20 interrupt */
|
||||
IRQN_GPIOHS21_INTERRUPT = 55, /*!< Hi-speed GPIO21 interrupt */
|
||||
IRQN_GPIOHS22_INTERRUPT = 56, /*!< Hi-speed GPIO22 interrupt */
|
||||
IRQN_GPIOHS23_INTERRUPT = 57, /*!< Hi-speed GPIO23 interrupt */
|
||||
IRQN_GPIOHS24_INTERRUPT = 58, /*!< Hi-speed GPIO24 interrupt */
|
||||
IRQN_GPIOHS25_INTERRUPT = 59, /*!< Hi-speed GPIO25 interrupt */
|
||||
IRQN_GPIOHS26_INTERRUPT = 60, /*!< Hi-speed GPIO26 interrupt */
|
||||
IRQN_GPIOHS27_INTERRUPT = 61, /*!< Hi-speed GPIO27 interrupt */
|
||||
IRQN_GPIOHS28_INTERRUPT = 62, /*!< Hi-speed GPIO28 interrupt */
|
||||
IRQN_GPIOHS29_INTERRUPT = 63, /*!< Hi-speed GPIO29 interrupt */
|
||||
IRQN_GPIOHS30_INTERRUPT = 64, /*!< Hi-speed GPIO30 interrupt */
|
||||
IRQN_GPIOHS31_INTERRUPT = 65, /*!< Hi-speed GPIO31 interrupt */
|
||||
IRQN_MAX
|
||||
} plic_irq_t;
|
||||
/* clang-format on */
|
||||
|
||||
/**
|
||||
* @brief Interrupt Source Priorities
|
||||
*
|
||||
* Each external interrupt source can be assigned a priority by
|
||||
* writing to its 32-bit memory-mapped priority register. The
|
||||
* number and value of supported priority levels can vary by
|
||||
* implementa- tion, with the simplest implementations having all
|
||||
* devices hardwired at priority 1, in which case, interrupts with
|
||||
* the lowest ID have the highest effective priority. The priority
|
||||
* registers are all WARL.
|
||||
*/
|
||||
typedef struct _plic_source_priorities
|
||||
{
|
||||
/* 0x0C000000: Reserved, 0x0C000004-0x0C000FFC: 1-1023 priorities */
|
||||
uint32_t priority[1024];
|
||||
} __attribute__((packed, aligned(4))) plic_source_priorities_t;
|
||||
|
||||
/**
|
||||
* @brief Interrupt Pending Bits
|
||||
*
|
||||
* The current status of the interrupt source pending bits in the
|
||||
* PLIC core can be read from the pending array, organized as 32
|
||||
* words of 32 bits. The pending bit for interrupt ID N is stored
|
||||
* in bit (N mod 32) of word (N/32). Bit 0 of word 0, which
|
||||
* represents the non-existent interrupt source 0, is always
|
||||
* hardwired to zero. The pending bits are read-only. A pending
|
||||
* bit in the PLIC core can be cleared by setting enable bits to
|
||||
* only enable the desired interrupt, then performing a claim. A
|
||||
* pending bit can be set by instructing the associated gateway to
|
||||
* send an interrupt service request.
|
||||
*/
|
||||
typedef struct _plic_pending_bits
|
||||
{
|
||||
/* 0x0C001000-0x0C00107C: Bit 0 is zero, Bits 1-1023 is pending bits */
|
||||
uint32_t u32[32];
|
||||
/* 0x0C001080-0x0C001FFF: Reserved */
|
||||
uint8_t resv[0xF80];
|
||||
} __attribute__((packed, aligned(4))) plic_pending_bits_t;
|
||||
|
||||
/**
|
||||
* @brief Target Interrupt Enables
|
||||
*
|
||||
* For each interrupt target, each device’s interrupt can be
|
||||
* enabled by setting the corresponding bit in that target’s
|
||||
* enables registers. The enables for a target are accessed as a
|
||||
* contiguous array of 32×32-bit words, packed the same way as the
|
||||
* pending bits. For each target, bit 0 of enable word 0
|
||||
* represents the non-existent interrupt ID 0 and is hardwired to
|
||||
* 0. Unused interrupt IDs are also hardwired to zero. The enables
|
||||
* arrays for different targets are packed contiguously in the
|
||||
* address space. Only 32-bit word accesses are supported by the
|
||||
* enables array in RV32 systems. Implementations can trap on
|
||||
* accesses to enables for non-existent targets, but must allow
|
||||
* access to the full enables array for any extant target,
|
||||
* treating all non-existent interrupt source’s enables as
|
||||
* hardwired to zero.
|
||||
*/
|
||||
typedef struct _plic_target_enables
|
||||
{
|
||||
/* 0x0C002000-0x0C1F1F80: target 0-15871 enables */
|
||||
struct
|
||||
{
|
||||
uint32_t enable[32 * 2];/* Offset 0x00-0x7C: Bit 0 is zero, Bits 1-1023 is bits*/
|
||||
} target[15872 / 2];
|
||||
|
||||
/* 0x0C1F2000-0x0C1FFFFC: Reserved, size 0xE000 */
|
||||
uint8_t resv[0xE000];
|
||||
} __attribute__((packed, aligned(4))) plic_target_enables_t;
|
||||
|
||||
/**
|
||||
* @brief PLIC Targets
|
||||
*
|
||||
* Target Priority Thresholds The threshold for a pending
|
||||
* interrupt priority that can interrupt each target can be set in
|
||||
* the target’s threshold register. The threshold is a WARL field,
|
||||
* where different implementations can support different numbers
|
||||
* of thresholds. The simplest implementation has a threshold
|
||||
* hardwired to zero.
|
||||
*
|
||||
* Target Claim Each target can perform a claim by reading the
|
||||
* claim/complete register, which returns the ID of the highest
|
||||
* priority pending interrupt or zero if there is no pending
|
||||
* interrupt for the target. A successful claim will also
|
||||
* atomically clear the corresponding pending bit on the interrupt
|
||||
* source. A target can perform a claim at any time, even if the
|
||||
* EIP is not set. The claim operation is not affected by the
|
||||
* setting of the target’s priority threshold register.
|
||||
*
|
||||
* Target Completion A target signals it has completed running a
|
||||
* handler by writing the interrupt ID it received from the claim
|
||||
* to the claim/complete register. This is routed to the
|
||||
* corresponding interrupt gateway, which can now send another
|
||||
* interrupt request to the PLIC. The PLIC does not check whether
|
||||
* the completion ID is the same as the last claim ID for that
|
||||
* target. If the completion ID does not match an interrupt source
|
||||
* that is currently enabled for the target, the completion is
|
||||
* silently ignored.
|
||||
*/
|
||||
typedef struct _plic_target
|
||||
{
|
||||
/* 0x0C200000-0x0FFFF004: target 0-15871 */
|
||||
struct {
|
||||
uint32_t priority_threshold;/* Offset 0x000 */
|
||||
uint32_t claim_complete; /* Offset 0x004 */
|
||||
uint8_t resv[0x1FF8]; /* Offset 0x008, Size 0xFF8 */
|
||||
} target[15872 / 2];
|
||||
} __attribute__((packed, aligned(4))) plic_target_t;
|
||||
|
||||
/**
|
||||
* @brief Platform-Level Interrupt Controller
|
||||
*
|
||||
* PLIC is Platform-Level Interrupt Controller. The PLIC complies
|
||||
* with the RISC-V Privileged Architecture specification, and can
|
||||
* support a maximum of 1023 external interrupt sources targeting
|
||||
* up to 15,872 core contexts.
|
||||
*/
|
||||
typedef struct _plic
|
||||
{
|
||||
/* 0x0C000000-0x0C000FFC */
|
||||
plic_source_priorities_t source_priorities;
|
||||
/* 0x0C001000-0x0C001FFF */
|
||||
const plic_pending_bits_t pending_bits;
|
||||
/* 0x0C002000-0x0C1FFFFC */
|
||||
plic_target_enables_t target_enables;
|
||||
/* 0x0C200000-0x0FFFF004 */
|
||||
plic_target_t targets;
|
||||
} __attribute__((packed, aligned(4))) plic_t;
|
||||
|
||||
extern volatile plic_t *const plic;
|
||||
|
||||
/**
|
||||
* @brief Definitions for the interrupt callbacks
|
||||
*/
|
||||
typedef int (*plic_irq_callback_t)(void *ctx);
|
||||
|
||||
/**
|
||||
* @brief Definitions for IRQ table instance
|
||||
*/
|
||||
typedef struct _plic_instance_t
|
||||
{
|
||||
plic_irq_callback_t callback;
|
||||
void *ctx;
|
||||
} plic_instance_t;
|
||||
|
||||
/**
|
||||
* @brief Initialize PLIC external interrupt
|
||||
*
|
||||
* @note This function will set MIP_MEIP. The MSTATUS_MIE must set by user.
|
||||
*
|
||||
* @return result
|
||||
* - 0 Success
|
||||
* - Other Fail
|
||||
*/
|
||||
void plic_init(void);
|
||||
|
||||
/**
|
||||
* @brief Enable PLIC external interrupt
|
||||
*
|
||||
* @param[in] irq_number external interrupt number
|
||||
*
|
||||
* @return result
|
||||
* - 0 Success
|
||||
* - Other Fail
|
||||
*/
|
||||
|
||||
int plic_irq_enable(plic_irq_t irq_number);
|
||||
|
||||
/**
|
||||
* @brief Disable PLIC external interrupt
|
||||
*
|
||||
* @param[in] irq_number The external interrupt number
|
||||
*
|
||||
* @return result
|
||||
* - 0 Success
|
||||
* - Other Fail
|
||||
*/
|
||||
int plic_irq_disable(plic_irq_t irq_number);
|
||||
|
||||
/**
|
||||
* @brief Set IRQ priority
|
||||
*
|
||||
* @param[in] irq_number The external interrupt number
|
||||
* @param[in] priority The priority of external interrupt number
|
||||
*
|
||||
* @return result
|
||||
* - 0 Success
|
||||
* - Other Fail
|
||||
*/
|
||||
int plic_set_priority(plic_irq_t irq_number, uint32_t priority);
|
||||
|
||||
/**
|
||||
* @brief Get IRQ priority
|
||||
*
|
||||
* @param[in] irq_number The external interrupt number
|
||||
*
|
||||
* @return The priority of external interrupt number
|
||||
*/
|
||||
uint32_t plic_get_priority(plic_irq_t irq_number);
|
||||
|
||||
/**
|
||||
* @brief Claim an IRQ
|
||||
*
|
||||
* @return The current IRQ number
|
||||
*/
|
||||
uint32_t plic_irq_claim(void);
|
||||
|
||||
/**
|
||||
* @brief Complete an IRQ
|
||||
*
|
||||
* @param[in] source The source IRQ number to complete
|
||||
*
|
||||
* @return result
|
||||
* - 0 Success
|
||||
* - Other Fail
|
||||
*/
|
||||
int plic_irq_complete(uint32_t source);
|
||||
|
||||
/**
|
||||
* @brief Register user callback function by IRQ number
|
||||
*
|
||||
* @param[in] irq The irq
|
||||
* @param[in] callback The callback
|
||||
* @param ctx The context
|
||||
*
|
||||
* @return result
|
||||
* - 0 Success
|
||||
* - Other Fail
|
||||
*/
|
||||
void plic_irq_register(plic_irq_t irq, plic_irq_callback_t callback, void *ctx);
|
||||
|
||||
/**
|
||||
* @brief Deegister user callback function by IRQ number
|
||||
*
|
||||
* @param[in] irq The irq
|
||||
*
|
||||
* @return result
|
||||
* - 0 Success
|
||||
* - Other Fail
|
||||
*/
|
||||
void plic_irq_deregister(plic_irq_t irq);
|
||||
|
||||
/**
|
||||
* @brief Deegister user callback function by IRQ number
|
||||
*
|
||||
* @param[in] irq The irq
|
||||
*
|
||||
* @return result
|
||||
* - 0 Success
|
||||
* - Other Fail
|
||||
*/
|
||||
void plic_irq_unregister(plic_irq_t irq);
|
||||
|
||||
/**
|
||||
* @brief Get IRQ table, Usage:
|
||||
* plic_instance_t (*plic_instance)[IRQN_MAX] = plic_get_instance();
|
||||
* ... plic_instance[x][y] ...;
|
||||
*
|
||||
* @return the point of IRQ table
|
||||
*/
|
||||
plic_instance_t (*plic_get_instance(void))[IRQN_MAX];
|
||||
|
||||
/* For c++ compatibility */
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _DRIVER_PLIC_H */
|
||||
@@ -1,74 +0,0 @@
|
||||
/* Copyright 2018 Canaan Inc.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* http://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 _DRIVER_PWM_H
|
||||
#define _DRIVER_PWM_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef enum _pwm_device_number
|
||||
{
|
||||
PWM_DEVICE_0,
|
||||
PWM_DEVICE_1,
|
||||
PWM_DEVICE_2,
|
||||
PWM_DEVICE_MAX,
|
||||
} pwm_device_number_t;
|
||||
|
||||
typedef enum _pwm_channel_number
|
||||
{
|
||||
PWM_CHANNEL_0,
|
||||
PWM_CHANNEL_1,
|
||||
PWM_CHANNEL_2,
|
||||
PWM_CHANNEL_3,
|
||||
PWM_CHANNEL_MAX,
|
||||
} pwm_channel_number_t;
|
||||
|
||||
/**
|
||||
* @brief Init pwm timer
|
||||
*
|
||||
* @param[in] timer timer
|
||||
*/
|
||||
void pwm_init(pwm_device_number_t pwm_number);
|
||||
|
||||
/**
|
||||
* @brief Enable timer
|
||||
*
|
||||
* @param[in] timer timer
|
||||
* @param[in] channel channel
|
||||
* @param[in] enable Enable or disable
|
||||
*
|
||||
*/
|
||||
void pwm_set_enable(pwm_device_number_t pwm_number, pwm_channel_number_t channel, int enable);
|
||||
|
||||
/**
|
||||
* @brief Set pwm duty
|
||||
*
|
||||
* @param[in] timer timer
|
||||
* @param[in] channel channel
|
||||
* @param[in] frequency pwm frequency
|
||||
* @param[in] duty duty
|
||||
*
|
||||
*/
|
||||
double pwm_set_frequency(pwm_device_number_t pwm_number, pwm_channel_number_t channel, double frequency, double duty);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _DRIVER_PWM_H */
|
||||
@@ -1,398 +0,0 @@
|
||||
/* Copyright 2018 Canaan Inc.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* http://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.
|
||||
*/
|
||||
/**
|
||||
* @file
|
||||
* @brief A real-time clock (RTC) is a computer clock that keeps track of
|
||||
* the current time.
|
||||
*/
|
||||
|
||||
#ifndef _DRIVER_RTC_H
|
||||
#define _DRIVER_RTC_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <time.h>
|
||||
#include "platform.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief RTC timer mode
|
||||
*
|
||||
* Timer mode selector
|
||||
* | Mode | Description |
|
||||
* |------|------------------------|
|
||||
* | 0 | Timer pause |
|
||||
* | 1 | Timer time running |
|
||||
* | 2 | Timer time setting |
|
||||
*/
|
||||
typedef enum _rtc_timer_mode_e
|
||||
{
|
||||
/* 0: Timer pause */
|
||||
RTC_TIMER_PAUSE,
|
||||
/* 1: Timer time running */
|
||||
RTC_TIMER_RUNNING,
|
||||
/* 2: Timer time setting */
|
||||
RTC_TIMER_SETTING,
|
||||
/* Max count of this enum*/
|
||||
RTC_TIMER_MAX
|
||||
} rtc_timer_mode_t;
|
||||
|
||||
/*
|
||||
* @brief RTC tick interrupt mode
|
||||
*
|
||||
* Tick interrupt mode selector
|
||||
* | Mode | Description |
|
||||
* |------|------------------------|
|
||||
* | 0 | Interrupt every second |
|
||||
* | 1 | Interrupt every minute |
|
||||
* | 2 | Interrupt every hour |
|
||||
* | 3 | Interrupt every day |
|
||||
*/
|
||||
typedef enum _rtc_tick_interrupt_mode_e
|
||||
{
|
||||
/* 0: Interrupt every second */
|
||||
RTC_INT_SECOND,
|
||||
/* 1: Interrupt every minute */
|
||||
RTC_INT_MINUTE,
|
||||
/* 2: Interrupt every hour */
|
||||
RTC_INT_HOUR,
|
||||
/* 3: Interrupt every day */
|
||||
RTC_INT_DAY,
|
||||
/* Max count of this enum*/
|
||||
RTC_INT_MAX
|
||||
} rtc_tick_interrupt_mode_t;
|
||||
|
||||
/**
|
||||
* @brief RTC mask structure
|
||||
*
|
||||
* RTC mask structure for common use
|
||||
*/
|
||||
typedef struct _rtc_mask
|
||||
{
|
||||
/* Reserved */
|
||||
uint32_t resv : 1;
|
||||
/* Second mask */
|
||||
uint32_t second : 1;
|
||||
/* Minute mask */
|
||||
uint32_t minute : 1;
|
||||
/* Hour mask */
|
||||
uint32_t hour : 1;
|
||||
/* Week mask */
|
||||
uint32_t week : 1;
|
||||
/* Day mask */
|
||||
uint32_t day : 1;
|
||||
/* Month mask */
|
||||
uint32_t month : 1;
|
||||
/* Year mask */
|
||||
uint32_t year : 1;
|
||||
} __attribute__((packed, aligned(1))) rtc_mask_t;
|
||||
|
||||
/**
|
||||
* @brief RTC register
|
||||
*
|
||||
* @note RTC register table
|
||||
*
|
||||
* | Offset | Name | Description |
|
||||
* |-----------|----------------|-------------------------------------|
|
||||
* | 0x00 | date | Timer date information |
|
||||
* | 0x04 | time | Timer time information |
|
||||
* | 0x08 | alarm_date | Alarm date information |
|
||||
* | 0x0c | alarm_time | Alarm time information |
|
||||
* | 0x10 | initial_count | Timer counter initial value |
|
||||
* | 0x14 | current_count | Timer counter current value |
|
||||
* | 0x18 | interrupt_ctrl | RTC interrupt settings |
|
||||
* | 0x1c | register_ctrl | RTC register settings |
|
||||
* | 0x20 | reserved0 | Reserved |
|
||||
* | 0x24 | reserved1 | Reserved |
|
||||
* | 0x28 | extended | Timer extended information |
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* @brief Timer date information
|
||||
*
|
||||
* No. 0 Register (0x00)
|
||||
*/
|
||||
typedef struct _rtc_date
|
||||
{
|
||||
/* Week. Range [0,6]. 0 is Sunday. */
|
||||
uint32_t week : 3;
|
||||
/* Reserved */
|
||||
uint32_t resv0 : 5;
|
||||
/* Day. Range [1,31] or [1,30] or [1,29] or [1,28] */
|
||||
uint32_t day : 5;
|
||||
/* Reserved */
|
||||
uint32_t resv1 : 3;
|
||||
/* Month. Range [1,12] */
|
||||
uint32_t month : 4;
|
||||
/* Year. Range [0,99] */
|
||||
uint32_t year : 12;
|
||||
} __attribute__((packed, aligned(4))) rtc_date_t;
|
||||
|
||||
/**
|
||||
* @brief Timer time information
|
||||
*
|
||||
* No. 1 Register (0x04)
|
||||
*/
|
||||
typedef struct _rtc_time
|
||||
{
|
||||
/* Reserved */
|
||||
uint32_t resv0 : 10;
|
||||
/* Second. Range [0,59] */
|
||||
uint32_t second : 6;
|
||||
/* Minute. Range [0,59] */
|
||||
uint32_t minute : 6;
|
||||
/* Reserved */
|
||||
uint32_t resv1 : 2;
|
||||
/* Hour. Range [0,23] */
|
||||
uint32_t hour : 5;
|
||||
/* Reserved */
|
||||
uint32_t resv2 : 3;
|
||||
} __attribute__((packed, aligned(4))) rtc_time_t;
|
||||
|
||||
/**
|
||||
* @brief Alarm date information
|
||||
*
|
||||
* No. 2 Register (0x08)
|
||||
*/
|
||||
typedef struct _rtc_alarm_date
|
||||
{
|
||||
/* Alarm Week. Range [0,6]. 0 is Sunday. */
|
||||
uint32_t week : 3;
|
||||
/* Reserved */
|
||||
uint32_t resv0 : 5;
|
||||
/* Alarm Day. Range [1,31] or [1,30] or [1,29] or [1,28] */
|
||||
uint32_t day : 5;
|
||||
/* Reserved */
|
||||
uint32_t resv1 : 3;
|
||||
/* Alarm Month. Range [1,12] */
|
||||
uint32_t month : 4;
|
||||
/* Alarm Year. Range [0,99] */
|
||||
uint32_t year : 12;
|
||||
} __attribute__((packed, aligned(4))) rtc_alarm_date_t;
|
||||
|
||||
/**
|
||||
* @brief Alarm time information
|
||||
*
|
||||
* No. 3 Register (0x0c)
|
||||
*/
|
||||
typedef struct _rtc_alarm_time
|
||||
{
|
||||
/* Reserved */
|
||||
uint32_t resv0 : 10;
|
||||
/* Alarm Second. Range [0,59] */
|
||||
uint32_t second : 6;
|
||||
/* Alarm Minute. Range [0,59] */
|
||||
uint32_t minute : 6;
|
||||
/* Reserved */
|
||||
uint32_t resv1 : 2;
|
||||
/* Alarm Hour. Range [0,23] */
|
||||
uint32_t hour : 5;
|
||||
/* Reserved */
|
||||
uint32_t resv2 : 3;
|
||||
} __attribute__((packed, aligned(4))) rtc_alarm_time_t;
|
||||
|
||||
/**
|
||||
* @brief Timer counter initial value
|
||||
*
|
||||
* No. 4 Register (0x10)
|
||||
*/
|
||||
typedef struct _rtc_initial_count
|
||||
{
|
||||
/* RTC counter initial value */
|
||||
uint32_t count : 32;
|
||||
} __attribute__((packed, aligned(4))) rtc_initial_count_t;
|
||||
|
||||
/**
|
||||
* @brief Timer counter current value
|
||||
*
|
||||
* No. 5 Register (0x14)
|
||||
*/
|
||||
typedef struct _rtc_current_count
|
||||
{
|
||||
/* RTC counter current value */
|
||||
uint32_t count : 32;
|
||||
} __attribute__((packed, aligned(4))) rtc_current_count_t;
|
||||
|
||||
/**
|
||||
* @brief RTC interrupt settings
|
||||
*
|
||||
* No. 6 Register (0x18)
|
||||
*/
|
||||
typedef struct _rtc_interrupt_ctrl
|
||||
{
|
||||
/* Reserved */
|
||||
uint32_t tick_enable : 1;
|
||||
/* Alarm interrupt enable */
|
||||
uint32_t alarm_enable : 1;
|
||||
/* Tick interrupt enable */
|
||||
uint32_t tick_int_mode : 2;
|
||||
/* Reserved */
|
||||
uint32_t resv : 20;
|
||||
/* Alarm compare mask for interrupt */
|
||||
uint32_t alarm_compare_mask : 8;
|
||||
} __attribute__((packed, aligned(4))) rtc_interrupt_ctrl_t;
|
||||
|
||||
/**
|
||||
* @brief RTC register settings
|
||||
*
|
||||
* No. 7 Register (0x1c)
|
||||
*/
|
||||
typedef struct _rtc_register_ctrl
|
||||
{
|
||||
/* RTC timer read enable */
|
||||
uint32_t read_enable : 1;
|
||||
/* RTC timer write enable */
|
||||
uint32_t write_enable : 1;
|
||||
/* Reserved */
|
||||
uint32_t resv0 : 11;
|
||||
/* RTC timer mask */
|
||||
uint32_t timer_mask : 8;
|
||||
/* RTC alarm mask */
|
||||
uint32_t alarm_mask : 8;
|
||||
/* RTC counter initial count value mask */
|
||||
uint32_t initial_count_mask : 1;
|
||||
/* RTC interrupt register mask */
|
||||
uint32_t interrupt_register_mask : 1;
|
||||
/* Reserved */
|
||||
uint32_t resv1 : 1;
|
||||
} __attribute__((packed, aligned(4))) rtc_register_ctrl_t;
|
||||
|
||||
/**
|
||||
* @brief Reserved
|
||||
*
|
||||
* No. 8 Register (0x20)
|
||||
*/
|
||||
typedef struct _rtc_reserved0
|
||||
{
|
||||
/* Reserved */
|
||||
uint32_t resv : 32;
|
||||
} __attribute__((packed, aligned(4))) rtc_reserved0_t;
|
||||
|
||||
/**
|
||||
* @brief Reserved
|
||||
*
|
||||
* No. 9 Register (0x24)
|
||||
*/
|
||||
typedef struct _rtc_reserved1
|
||||
{
|
||||
/* Reserved */
|
||||
uint32_t resv : 32;
|
||||
} __attribute__((packed, aligned(4))) rtc_reserved1_t;
|
||||
|
||||
/**
|
||||
* @brief Timer extended information
|
||||
*
|
||||
* No. 10 Register (0x28)
|
||||
*/
|
||||
typedef struct _rtc_extended
|
||||
{
|
||||
/* Century. Range [0,31] */
|
||||
uint32_t century : 5;
|
||||
/* Is leap year. 1 is leap year, 0 is not leap year */
|
||||
uint32_t leap_year : 1;
|
||||
/* Reserved */
|
||||
uint32_t resv : 26;
|
||||
} __attribute__((packed, aligned(4))) rtc_extended_t;
|
||||
|
||||
|
||||
/**
|
||||
* @brief Real-time clock struct
|
||||
*
|
||||
* A real-time clock (RTC) is a computer clock that keeps track of
|
||||
* the current time.
|
||||
*/
|
||||
typedef struct _rtc
|
||||
{
|
||||
/* No. 0 (0x00): Timer date information */
|
||||
rtc_date_t date;
|
||||
/* No. 1 (0x04): Timer time information */
|
||||
rtc_time_t time;
|
||||
/* No. 2 (0x08): Alarm date information */
|
||||
rtc_alarm_date_t alarm_date;
|
||||
/* No. 3 (0x0c): Alarm time information */
|
||||
rtc_alarm_time_t alarm_time;
|
||||
/* No. 4 (0x10): Timer counter initial value */
|
||||
rtc_initial_count_t initial_count;
|
||||
/* No. 5 (0x14): Timer counter current value */
|
||||
rtc_current_count_t current_count;
|
||||
/* No. 6 (0x18): RTC interrupt settings */
|
||||
rtc_interrupt_ctrl_t interrupt_ctrl;
|
||||
/* No. 7 (0x1c): RTC register settings */
|
||||
rtc_register_ctrl_t register_ctrl;
|
||||
/* No. 8 (0x20): Reserved */
|
||||
rtc_reserved0_t reserved0;
|
||||
/* No. 9 (0x24): Reserved */
|
||||
rtc_reserved1_t reserved1;
|
||||
/* No. 10 (0x28): Timer extended information */
|
||||
rtc_extended_t extended;
|
||||
} __attribute__((packed, aligned(4))) rtc_t;
|
||||
|
||||
|
||||
/**
|
||||
* @brief Real-time clock object
|
||||
*/
|
||||
extern volatile rtc_t *const rtc;
|
||||
extern volatile uint32_t *const rtc_base;
|
||||
|
||||
/**
|
||||
* @brief Set date time to RTC
|
||||
*
|
||||
* @param[in] year The year
|
||||
* @param[in] month The month
|
||||
* @param[in] day The day
|
||||
* @param[in] hour The hour
|
||||
* @param[in] minute The minute
|
||||
* @param[in] second The second
|
||||
*
|
||||
* @return result
|
||||
* - 0 Success
|
||||
* - Other Fail
|
||||
*/
|
||||
int rtc_timer_set(int year, int month, int day, int hour, int minute, int second);
|
||||
|
||||
/**
|
||||
* @brief Get date time from RTC
|
||||
*
|
||||
* @param year The year
|
||||
* @param month The month
|
||||
* @param day The day
|
||||
* @param hour The hour
|
||||
* @param minute The minute
|
||||
* @param second The second
|
||||
*
|
||||
* @return result
|
||||
* - 0 Success
|
||||
* - Other Fail
|
||||
*/
|
||||
int rtc_timer_get(int *year, int *month, int *day, int *hour, int *minute, int *second);
|
||||
|
||||
/**
|
||||
* @brief Initialize RTC
|
||||
*
|
||||
* @return Result
|
||||
* - 0 Success
|
||||
* - Other Fail
|
||||
*/
|
||||
int rtc_init(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _DRIVER_RTC_H */
|
||||
@@ -1,128 +0,0 @@
|
||||
/* Copyright 2018 Canaan Inc.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* http://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 _SHA256_H
|
||||
#define _SHA256_H
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define ENABLE_SHA (0x1)
|
||||
#define SHA256_BIG_ENDIAN (0x1)
|
||||
|
||||
#define SHA256_HASH_LEN 32
|
||||
#define SHA256_HASH_WORDS 8
|
||||
#define SHA256_BLOCK_LEN 64L
|
||||
|
||||
typedef struct _sha_num_reg
|
||||
{
|
||||
/* The total amount of data calculated by SHA256 is set by this register, and the smallest unit is 512bit. */
|
||||
uint32_t sha_data_cnt : 16;
|
||||
/* currently calculated block number. 512bit=1block*/
|
||||
uint32_t sha_data_num : 16;
|
||||
} __attribute__((packed, aligned(4))) sha_num_reg_t;
|
||||
|
||||
typedef struct _sha_function_reg_0
|
||||
{
|
||||
/* write:SHA256 enable register. read:Calculation completed flag */
|
||||
uint32_t sha_en : 1;
|
||||
uint32_t reserved00 : 7;
|
||||
/* SHA256 calculation overflow flag */
|
||||
uint32_t sha_overflow : 1;
|
||||
uint32_t reserved01 : 7;
|
||||
/* Endian setting; b'0:little endian b'1:big endian */
|
||||
uint32_t sha_endian : 1;
|
||||
uint32_t reserved02 : 15;
|
||||
} __attribute__((packed, aligned(4))) sha_function_reg_0_t;
|
||||
|
||||
typedef struct _sha_function_reg_1
|
||||
{
|
||||
/* Sha and DMA handshake signals enable.b'1:enable;b'0:disable */
|
||||
uint32_t dma_en : 1;
|
||||
uint32_t reserved10 : 7;
|
||||
/* b'1:sha256 fifo is full; b'0:not full */
|
||||
uint32_t fifo_in_full : 1;
|
||||
uint32_t reserved11 : 23;
|
||||
} __attribute__((packed, aligned(4))) sha_function_reg_1_t;
|
||||
|
||||
typedef struct _sha256
|
||||
{
|
||||
/* Calculated sha256 return value. */
|
||||
uint32_t sha_result[8];
|
||||
/* SHA256 input data from this register. */
|
||||
uint32_t sha_data_in1;
|
||||
uint32_t reselved0;
|
||||
sha_num_reg_t sha_num_reg;
|
||||
sha_function_reg_0_t sha_function_reg_0;
|
||||
uint32_t reserved1;
|
||||
sha_function_reg_1_t sha_function_reg_1;
|
||||
} __attribute__((packed, aligned(4))) sha256_t;
|
||||
|
||||
typedef struct _sha256_context
|
||||
{
|
||||
size_t total_len;
|
||||
size_t buffer_len;
|
||||
union
|
||||
{
|
||||
uint32_t words[16];
|
||||
uint8_t bytes[64];
|
||||
} buffer;
|
||||
} sha256_context_t;
|
||||
|
||||
/**
|
||||
* @brief Init SHA256 calculation context
|
||||
*
|
||||
* @param[in] context SHA256 context object
|
||||
*
|
||||
*/
|
||||
void sha256_init(sha256_context_t *context, size_t input_len);
|
||||
|
||||
/**
|
||||
* @brief Called repeatedly with chunks of the message to be hashed
|
||||
*
|
||||
* @param[in] context SHA256 context object
|
||||
* @param[in] data_buf data chunk to be hashed
|
||||
* @param[in] buf_len length of data chunk
|
||||
*
|
||||
*/
|
||||
void sha256_update(sha256_context_t *context, const void *input, size_t input_len);
|
||||
|
||||
/**
|
||||
* @brief Finish SHA256 hash process, output the result.
|
||||
*
|
||||
* @param[in] context SHA256 context object
|
||||
* @param[out] output The buffer where SHA256 hash will be output
|
||||
*
|
||||
*/
|
||||
void sha256_final(sha256_context_t *context, uint8_t *output);
|
||||
|
||||
/**
|
||||
* @brief Simple SHA256 hash once.
|
||||
*
|
||||
* @param[in] data Data will be hashed
|
||||
* @param[in] data_len Data length
|
||||
* @param[out] output Output buffer
|
||||
*
|
||||
*/
|
||||
void sha256_hard_calculate(const uint8_t *input, size_t input_len, uint8_t *output);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,460 +0,0 @@
|
||||
/* Copyright 2018 Canaan Inc.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* http://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 _DRIVER_SPI_H
|
||||
#define _DRIVER_SPI_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include "dmac.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* clang-format off */
|
||||
typedef struct _spi
|
||||
{
|
||||
/* SPI Control Register 0 (0x00)*/
|
||||
volatile uint32_t ctrlr0;
|
||||
/* SPI Control Register 1 (0x04)*/
|
||||
volatile uint32_t ctrlr1;
|
||||
/* SPI Enable Register (0x08)*/
|
||||
volatile uint32_t ssienr;
|
||||
/* SPI Microwire Control Register (0x0c)*/
|
||||
volatile uint32_t mwcr;
|
||||
/* SPI Slave Enable Register (0x10)*/
|
||||
volatile uint32_t ser;
|
||||
/* SPI Baud Rate Select (0x14)*/
|
||||
volatile uint32_t baudr;
|
||||
/* SPI Transmit FIFO Threshold Level (0x18)*/
|
||||
volatile uint32_t txftlr;
|
||||
/* SPI Receive FIFO Threshold Level (0x1c)*/
|
||||
volatile uint32_t rxftlr;
|
||||
/* SPI Transmit FIFO Level Register (0x20)*/
|
||||
volatile uint32_t txflr;
|
||||
/* SPI Receive FIFO Level Register (0x24)*/
|
||||
volatile uint32_t rxflr;
|
||||
/* SPI Status Register (0x28)*/
|
||||
volatile uint32_t sr;
|
||||
/* SPI Interrupt Mask Register (0x2c)*/
|
||||
volatile uint32_t imr;
|
||||
/* SPI Interrupt Status Register (0x30)*/
|
||||
volatile uint32_t isr;
|
||||
/* SPI Raw Interrupt Status Register (0x34)*/
|
||||
volatile uint32_t risr;
|
||||
/* SPI Transmit FIFO Overflow Interrupt Clear Register (0x38)*/
|
||||
volatile uint32_t txoicr;
|
||||
/* SPI Receive FIFO Overflow Interrupt Clear Register (0x3c)*/
|
||||
volatile uint32_t rxoicr;
|
||||
/* SPI Receive FIFO Underflow Interrupt Clear Register (0x40)*/
|
||||
volatile uint32_t rxuicr;
|
||||
/* SPI Multi-Master Interrupt Clear Register (0x44)*/
|
||||
volatile uint32_t msticr;
|
||||
/* SPI Interrupt Clear Register (0x48)*/
|
||||
volatile uint32_t icr;
|
||||
/* SPI DMA Control Register (0x4c)*/
|
||||
volatile uint32_t dmacr;
|
||||
/* SPI DMA Transmit Data Level (0x50)*/
|
||||
volatile uint32_t dmatdlr;
|
||||
/* SPI DMA Receive Data Level (0x54)*/
|
||||
volatile uint32_t dmardlr;
|
||||
/* SPI Identification Register (0x58)*/
|
||||
volatile uint32_t idr;
|
||||
/* SPI DWC_ssi component version (0x5c)*/
|
||||
volatile uint32_t ssic_version_id;
|
||||
/* SPI Data Register 0-36 (0x60 -- 0xec)*/
|
||||
volatile uint32_t dr[36];
|
||||
/* SPI RX Sample Delay Register (0xf0)*/
|
||||
volatile uint32_t rx_sample_delay;
|
||||
/* SPI SPI Control Register (0xf4)*/
|
||||
volatile uint32_t spi_ctrlr0;
|
||||
/* reserved (0xf8)*/
|
||||
volatile uint32_t resv;
|
||||
/* SPI XIP Mode bits (0xfc)*/
|
||||
volatile uint32_t xip_mode_bits;
|
||||
/* SPI XIP INCR transfer opcode (0x100)*/
|
||||
volatile uint32_t xip_incr_inst;
|
||||
/* SPI XIP WRAP transfer opcode (0x104)*/
|
||||
volatile uint32_t xip_wrap_inst;
|
||||
/* SPI XIP Control Register (0x108)*/
|
||||
volatile uint32_t xip_ctrl;
|
||||
/* SPI XIP Slave Enable Register (0x10c)*/
|
||||
volatile uint32_t xip_ser;
|
||||
/* SPI XIP Receive FIFO Overflow Interrupt Clear Register (0x110)*/
|
||||
volatile uint32_t xrxoicr;
|
||||
/* SPI XIP time out register for continuous transfers (0x114)*/
|
||||
volatile uint32_t xip_cnt_time_out;
|
||||
volatile uint32_t endian;
|
||||
} __attribute__((packed, aligned(4))) spi_t;
|
||||
/* clang-format on */
|
||||
|
||||
typedef enum _spi_device_num
|
||||
{
|
||||
SPI_DEVICE_0,
|
||||
SPI_DEVICE_1,
|
||||
SPI_DEVICE_2,
|
||||
SPI_DEVICE_3,
|
||||
SPI_DEVICE_MAX,
|
||||
} spi_device_num_t;
|
||||
|
||||
typedef enum _spi_work_mode
|
||||
{
|
||||
SPI_WORK_MODE_0,
|
||||
SPI_WORK_MODE_1,
|
||||
SPI_WORK_MODE_2,
|
||||
SPI_WORK_MODE_3,
|
||||
} spi_work_mode_t;
|
||||
|
||||
typedef enum _spi_frame_format
|
||||
{
|
||||
SPI_FF_STANDARD,
|
||||
SPI_FF_DUAL,
|
||||
SPI_FF_QUAD,
|
||||
SPI_FF_OCTAL
|
||||
} spi_frame_format_t;
|
||||
|
||||
typedef enum _spi_instruction_address_trans_mode
|
||||
{
|
||||
SPI_AITM_STANDARD,
|
||||
SPI_AITM_ADDR_STANDARD,
|
||||
SPI_AITM_AS_FRAME_FORMAT
|
||||
} spi_instruction_address_trans_mode_t;
|
||||
|
||||
typedef enum _spi_transfer_mode
|
||||
{
|
||||
SPI_TMOD_TRANS_RECV,
|
||||
SPI_TMOD_TRANS,
|
||||
SPI_TMOD_RECV,
|
||||
SPI_TMOD_EEROM
|
||||
} spi_transfer_mode_t;
|
||||
|
||||
|
||||
typedef enum _spi_transfer_width
|
||||
{
|
||||
SPI_TRANS_CHAR = 0x1,
|
||||
SPI_TRANS_SHORT = 0x2,
|
||||
SPI_TRANS_INT = 0x4,
|
||||
} spi_transfer_width_t;
|
||||
|
||||
typedef enum _spi_chip_select
|
||||
{
|
||||
SPI_CHIP_SELECT_0,
|
||||
SPI_CHIP_SELECT_1,
|
||||
SPI_CHIP_SELECT_2,
|
||||
SPI_CHIP_SELECT_3,
|
||||
SPI_CHIP_SELECT_MAX,
|
||||
} spi_chip_select_t;
|
||||
|
||||
typedef enum {
|
||||
WRITE_CONFIG,
|
||||
READ_CONFIG,
|
||||
WRITE_DATA_BYTE,
|
||||
READ_DATA_BYTE,
|
||||
WRITE_DATA_BLOCK,
|
||||
READ_DATA_BLOCK,
|
||||
} spi_slave_command_e;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8_t cmd;
|
||||
uint8_t err;
|
||||
uint32_t addr;
|
||||
uint32_t len;
|
||||
} spi_slave_command_t;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
IDLE,
|
||||
COMMAND,
|
||||
TRANSFER,
|
||||
} spi_slave_status_e;
|
||||
|
||||
typedef int (*spi_slave_receive_callback_t)(void *ctx);
|
||||
|
||||
typedef struct _spi_slave_instance
|
||||
{
|
||||
uint8_t int_pin;
|
||||
uint8_t ready_pin;
|
||||
dmac_channel_number_t dmac_channel;
|
||||
uint8_t dfs;
|
||||
uint8_t slv_oe;
|
||||
uint8_t work_mode;
|
||||
size_t data_bit_length;
|
||||
volatile spi_slave_status_e status;
|
||||
volatile spi_slave_command_t command;
|
||||
volatile uint8_t *config_ptr;
|
||||
uint32_t config_len;
|
||||
spi_slave_receive_callback_t callback;
|
||||
} spi_slave_instance_t;
|
||||
|
||||
extern volatile spi_t *const spi[4];
|
||||
|
||||
/**
|
||||
* @brief Set spi configuration
|
||||
*
|
||||
* @param[in] spi_num Spi bus number
|
||||
* @param[in] mode Spi mode
|
||||
* @param[in] frame_format Spi frame format
|
||||
* @param[in] data_bit_length Spi data bit length
|
||||
* @param[in] endian 0:little-endian 1:big-endian
|
||||
*
|
||||
* @return Void
|
||||
*/
|
||||
void spi_init(spi_device_num_t spi_num, spi_work_mode_t work_mode, spi_frame_format_t frame_format,
|
||||
size_t data_bit_length, uint32_t endian);
|
||||
|
||||
/**
|
||||
* @brief Set multiline configuration
|
||||
*
|
||||
* @param[in] spi_num Spi bus number
|
||||
* @param[in] instruction_length Instruction length
|
||||
* @param[in] address_length Address length
|
||||
* @param[in] wait_cycles Wait cycles
|
||||
* @param[in] instruction_address_trans_mode Spi transfer mode
|
||||
*
|
||||
*/
|
||||
void spi_init_non_standard(spi_device_num_t spi_num, uint32_t instruction_length, uint32_t address_length,
|
||||
uint32_t wait_cycles, spi_instruction_address_trans_mode_t instruction_address_trans_mode);
|
||||
|
||||
/**
|
||||
* @brief Spi send data
|
||||
*
|
||||
* @param[in] spi_num Spi bus number
|
||||
* @param[in] chip_select Spi chip select
|
||||
* @param[in] cmd_buff Spi command buffer point
|
||||
* @param[in] cmd_len Spi command length
|
||||
* @param[in] tx_buff Spi transmit buffer point
|
||||
* @param[in] tx_len Spi transmit buffer length
|
||||
*
|
||||
* @return Result
|
||||
* - 0 Success
|
||||
* - Other Fail
|
||||
*/
|
||||
void spi_send_data_standard(spi_device_num_t spi_num, spi_chip_select_t chip_select, const uint8_t *cmd_buff,
|
||||
size_t cmd_len, const uint8_t *tx_buff, size_t tx_len);
|
||||
|
||||
/**
|
||||
* @brief Spi receive data
|
||||
*
|
||||
* @param[in] spi_num Spi bus number
|
||||
* @param[in] chip_select Spi chip select
|
||||
* @param[in] cmd_buff Spi command buffer point
|
||||
* @param[in] cmd_len Spi command length
|
||||
* @param[in] rx_buff Spi receive buffer point
|
||||
* @param[in] rx_len Spi receive buffer length
|
||||
*
|
||||
* @return Result
|
||||
* - 0 Success
|
||||
* - Other Fail
|
||||
*/
|
||||
void spi_receive_data_standard(spi_device_num_t spi_num, spi_chip_select_t chip_select, const uint8_t *cmd_buff,
|
||||
size_t cmd_len, uint8_t *rx_buff, size_t rx_len);
|
||||
|
||||
/**
|
||||
* @brief Spi special receive data
|
||||
*
|
||||
* @param[in] spi_num Spi bus number
|
||||
* @param[in] chip_select Spi chip select
|
||||
* @param[in] cmd_buff Spi command buffer point
|
||||
* @param[in] cmd_len Spi command length
|
||||
* @param[in] rx_buff Spi receive buffer point
|
||||
* @param[in] rx_len Spi receive buffer length
|
||||
*
|
||||
* @return Result
|
||||
* - 0 Success
|
||||
* - Other Fail
|
||||
*/
|
||||
void spi_receive_data_multiple(spi_device_num_t spi_num, spi_chip_select_t chip_select, const uint32_t *cmd_buff,
|
||||
size_t cmd_len, uint8_t *rx_buff, size_t rx_len);
|
||||
|
||||
/**
|
||||
* @brief Spi special send data
|
||||
*
|
||||
* @param[in] spi_num Spi bus number
|
||||
* @param[in] chip_select Spi chip select
|
||||
* @param[in] cmd_buff Spi command buffer point
|
||||
* @param[in] cmd_len Spi command length
|
||||
* @param[in] tx_buff Spi transmit buffer point
|
||||
* @param[in] tx_len Spi transmit buffer length
|
||||
*
|
||||
* @return Result
|
||||
* - 0 Success
|
||||
* - Other Fail
|
||||
*/
|
||||
void spi_send_data_multiple(spi_device_num_t spi_num, spi_chip_select_t chip_select, const uint32_t *cmd_buff,
|
||||
size_t cmd_len, const uint8_t *tx_buff, size_t tx_len);
|
||||
|
||||
/**
|
||||
* @brief Spi send data by dma
|
||||
*
|
||||
* @param[in] channel_num Dmac channel number
|
||||
* @param[in] spi_num Spi bus number
|
||||
* @param[in] chip_select Spi chip select
|
||||
* @param[in] cmd_buff Spi command buffer point
|
||||
* @param[in] cmd_len Spi command length
|
||||
* @param[in] tx_buff Spi transmit buffer point
|
||||
* @param[in] tx_len Spi transmit buffer length
|
||||
*
|
||||
* @return Result
|
||||
* - 0 Success
|
||||
* - Other Fail
|
||||
*/
|
||||
void spi_send_data_standard_dma(dmac_channel_number_t channel_num, spi_device_num_t spi_num,
|
||||
spi_chip_select_t chip_select,
|
||||
const uint8_t *cmd_buff, size_t cmd_len, const uint8_t *tx_buff, size_t tx_len);
|
||||
|
||||
/**
|
||||
* @brief Spi receive data by dma
|
||||
*
|
||||
* @param[in] w_channel_num Dmac write channel number
|
||||
* @param[in] r_channel_num Dmac read channel number
|
||||
* @param[in] spi_num Spi bus number
|
||||
* @param[in] chip_select Spi chip select
|
||||
* @param[in] cmd_buff Spi command buffer point
|
||||
* @param[in] cmd_len Spi command length
|
||||
* @param[in] rx_buff Spi receive buffer point
|
||||
* @param[in] rx_len Spi receive buffer length
|
||||
*
|
||||
* @return Result
|
||||
* - 0 Success
|
||||
* - Other Fail
|
||||
*/
|
||||
void spi_receive_data_standard_dma(dmac_channel_number_t dma_send_channel_num,
|
||||
dmac_channel_number_t dma_receive_channel_num,
|
||||
spi_device_num_t spi_num, spi_chip_select_t chip_select, const uint8_t *cmd_buff,
|
||||
size_t cmd_len, uint8_t *rx_buff, size_t rx_len);
|
||||
|
||||
/**
|
||||
* @brief Spi special send data by dma
|
||||
*
|
||||
* @param[in] channel_num Dmac channel number
|
||||
* @param[in] spi_num Spi bus number
|
||||
* @param[in] chip_select Spi chip select
|
||||
* @param[in] cmd_buff Spi command buffer point
|
||||
* @param[in] cmd_len Spi command length
|
||||
* @param[in] tx_buff Spi transmit buffer point
|
||||
* @param[in] tx_len Spi transmit buffer length
|
||||
*
|
||||
* @return Result
|
||||
* - 0 Success
|
||||
* - Other Fail
|
||||
*/
|
||||
void spi_send_data_multiple_dma(dmac_channel_number_t channel_num, spi_device_num_t spi_num,
|
||||
spi_chip_select_t chip_select,
|
||||
const uint32_t *cmd_buff, size_t cmd_len, const uint8_t *tx_buff, size_t tx_len);
|
||||
|
||||
/**
|
||||
* @brief Spi special receive data by dma
|
||||
*
|
||||
* @param[in] dma_send_channel_num Dmac write channel number
|
||||
* @param[in] dma_receive_channel_num Dmac read channel number
|
||||
* @param[in] spi_num Spi bus number
|
||||
* @param[in] chip_select Spi chip select
|
||||
* @param[in] cmd_buff Spi command buffer point
|
||||
* @param[in] cmd_len Spi command length
|
||||
* @param[in] rx_buff Spi receive buffer point
|
||||
* @param[in] rx_len Spi receive buffer length
|
||||
*
|
||||
* @return Result
|
||||
* - 0 Success
|
||||
* - Other Fail
|
||||
*/
|
||||
void spi_receive_data_multiple_dma(dmac_channel_number_t dma_send_channel_num,
|
||||
dmac_channel_number_t dma_receive_channel_num,
|
||||
spi_device_num_t spi_num, spi_chip_select_t chip_select, const uint32_t *cmd_buff,
|
||||
size_t cmd_len, uint8_t *rx_buff, size_t rx_len);
|
||||
|
||||
/**
|
||||
* @brief Spi fill dma
|
||||
*
|
||||
* @param[in] channel_num Dmac channel number
|
||||
* @param[in] spi_num Spi bus number
|
||||
* @param[in] chip_select Spi chip select
|
||||
* @param[in] tx_buff Spi command buffer point
|
||||
* @param[in] tx_len Spi command length
|
||||
*
|
||||
* @return Result
|
||||
* - 0 Success
|
||||
* - Other Fail
|
||||
*/
|
||||
void spi_fill_data_dma(dmac_channel_number_t channel_num, spi_device_num_t spi_num, spi_chip_select_t chip_select,
|
||||
const uint32_t *tx_buff, size_t tx_len);
|
||||
|
||||
/**
|
||||
* @brief Spi normal send by dma
|
||||
*
|
||||
* @param[in] channel_num Dmac channel number
|
||||
* @param[in] spi_num Spi bus number
|
||||
* @param[in] chip_select Spi chip select
|
||||
* @param[in] tx_buff Spi transmit buffer point
|
||||
* @param[in] tx_len Spi transmit buffer length
|
||||
* @param[in] stw Spi transfer width
|
||||
*
|
||||
* @return Result
|
||||
* - 0 Success
|
||||
* - Other Fail
|
||||
*/
|
||||
void spi_send_data_normal_dma(dmac_channel_number_t channel_num, spi_device_num_t spi_num,
|
||||
spi_chip_select_t chip_select,
|
||||
const void *tx_buff, size_t tx_len, spi_transfer_width_t spi_transfer_width);
|
||||
|
||||
/**
|
||||
* @brief Spi normal send by dma
|
||||
*
|
||||
* @param[in] spi_num Spi bus number
|
||||
* @param[in] spi_clk Spi clock rate
|
||||
*
|
||||
* @return The real spi clock rate
|
||||
*/
|
||||
uint32_t spi_set_clk_rate(spi_device_num_t spi_num, uint32_t spi_clk);
|
||||
|
||||
/**
|
||||
* @brief Spi full duplex send receive data by dma
|
||||
*
|
||||
* @param[in] dma_send_channel_num Dmac write channel number
|
||||
* @param[in] dma_receive_channel_num Dmac read channel number
|
||||
* @param[in] spi_num Spi bus number
|
||||
* @param[in] chip_select Spi chip select
|
||||
* @param[in] tx_buf Spi send buffer
|
||||
* @param[in] tx_len Spi send buffer length
|
||||
* @param[in] rx_buf Spi receive buffer
|
||||
* @param[in] rx_len Spi receive buffer length
|
||||
*
|
||||
*/
|
||||
void spi_dup_send_receive_data_dma(dmac_channel_number_t dma_send_channel_num,
|
||||
dmac_channel_number_t dma_receive_channel_num,
|
||||
spi_device_num_t spi_num, spi_chip_select_t chip_select,
|
||||
const uint8_t *tx_buf, size_t tx_len, uint8_t *rx_buf, size_t rx_len);
|
||||
|
||||
/**
|
||||
* @brief Set spi slave configuration
|
||||
*
|
||||
* @param[in] int_pin SPI master starts sending data interrupt.
|
||||
* @param[in] ready_pin SPI slave ready.
|
||||
* @param[in] dmac_channel Dmac channel number for block.
|
||||
* @param[in] data_bit_length Spi data bit length
|
||||
* @param[in] data SPI slave device data buffer.
|
||||
* @param[in] len The length of SPI slave device data buffer.
|
||||
* @param[in] callback Callback of spi slave.
|
||||
*
|
||||
* @return Void
|
||||
*/
|
||||
void spi_slave_config(uint8_t int_pin, uint8_t ready_pin, dmac_channel_number_t dmac_channel, size_t data_bit_length, uint8_t *data, uint32_t len, spi_slave_receive_callback_t callback);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _DRIVER_SPI_H */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,161 +0,0 @@
|
||||
/* Copyright 2018 Canaan Inc.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* http://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 _DRIVER_TIMER_H
|
||||
#define _DRIVER_TIMER_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* clang-format off */
|
||||
typedef struct _timer_channel
|
||||
{
|
||||
/* TIMER_N Load Count Register (0x00+(N-1)*0x14) */
|
||||
volatile uint32_t load_count;
|
||||
/* TIMER_N Current Value Register (0x04+(N-1)*0x14) */
|
||||
volatile uint32_t current_value;
|
||||
/* TIMER_N Control Register (0x08+(N-1)*0x14) */
|
||||
volatile uint32_t control;
|
||||
/* TIMER_N Interrupt Clear Register (0x0c+(N-1)*0x14) */
|
||||
volatile uint32_t eoi;
|
||||
/* TIMER_N Interrupt Status Register (0x10+(N-1)*0x14) */
|
||||
volatile uint32_t intr_stat;
|
||||
} __attribute__((packed, aligned(4))) timer_channel_t;
|
||||
|
||||
typedef struct _kendryte_timer
|
||||
{
|
||||
/* TIMER_N Register (0x00-0x4c) */
|
||||
volatile timer_channel_t channel[4];
|
||||
/* reserverd (0x50-0x9c) */
|
||||
volatile uint32_t resv1[20];
|
||||
/* TIMER Interrupt Status Register (0xa0) */
|
||||
volatile uint32_t intr_stat;
|
||||
/* TIMER Interrupt Clear Register (0xa4) */
|
||||
volatile uint32_t eoi;
|
||||
/* TIMER Raw Interrupt Status Register (0xa8) */
|
||||
volatile uint32_t raw_intr_stat;
|
||||
/* TIMER Component Version Register (0xac) */
|
||||
volatile uint32_t comp_version;
|
||||
/* TIMER_N Load Count2 Register (0xb0-0xbc) */
|
||||
volatile uint32_t load_count2[4];
|
||||
} __attribute__((packed, aligned(4))) kendryte_timer_t;
|
||||
|
||||
typedef enum _timer_deivce_number
|
||||
{
|
||||
TIMER_DEVICE_0,
|
||||
TIMER_DEVICE_1,
|
||||
TIMER_DEVICE_2,
|
||||
TIMER_DEVICE_MAX,
|
||||
} timer_device_number_t;
|
||||
|
||||
typedef enum _timer_channel_number
|
||||
{
|
||||
TIMER_CHANNEL_0,
|
||||
TIMER_CHANNEL_1,
|
||||
TIMER_CHANNEL_2,
|
||||
TIMER_CHANNEL_3,
|
||||
TIMER_CHANNEL_MAX,
|
||||
} timer_channel_number_t;
|
||||
|
||||
/* TIMER Control Register */
|
||||
#define TIMER_CR_ENABLE 0x00000001
|
||||
#define TIMER_CR_MODE_MASK 0x00000002
|
||||
#define TIMER_CR_FREE_MODE 0x00000000
|
||||
#define TIMER_CR_USER_MODE 0x00000002
|
||||
#define TIMER_CR_INTERRUPT_MASK 0x00000004
|
||||
#define TIMER_CR_PWM_ENABLE 0x00000008
|
||||
/* clang-format on */
|
||||
|
||||
extern volatile kendryte_timer_t *const timer[3];
|
||||
|
||||
/**
|
||||
* @brief Definitions for the timer callbacks
|
||||
*/
|
||||
typedef int (*timer_callback_t)(void *ctx);
|
||||
|
||||
/**
|
||||
* @brief Set timer timeout
|
||||
*
|
||||
* @param[in] timer timer
|
||||
* @param[in] channel channel
|
||||
* @param[in] nanoseconds timeout
|
||||
*
|
||||
* @return the real timeout
|
||||
*/
|
||||
size_t timer_set_interval(timer_device_number_t timer_number, timer_channel_number_t channel, size_t nanoseconds);
|
||||
|
||||
/**
|
||||
* @brief Init timer
|
||||
*
|
||||
* @param[in] timer timer
|
||||
*/
|
||||
void timer_init(timer_device_number_t timer_number);
|
||||
|
||||
/**
|
||||
* @brief [DEPRECATED] Set timer timeout function
|
||||
*
|
||||
* @param[in] timer timer
|
||||
* @param[in] channel channel
|
||||
* @param[in] func timeout function
|
||||
* @param[in] priority interrupt priority
|
||||
*
|
||||
*/
|
||||
void timer_set_irq(timer_device_number_t timer_number, timer_channel_number_t channel, void(*func)(), uint32_t priority);
|
||||
|
||||
/**
|
||||
* @brief Register timer interrupt user callback function
|
||||
*
|
||||
* @param[in] device The timer device number
|
||||
* @param[in] channel The channel
|
||||
* @param[in] is_one_shot Indicates if single shot
|
||||
* @param[in] priority The priority
|
||||
* @param[in] callback The callback function
|
||||
* @param[in] ctx The context
|
||||
*
|
||||
* @return result
|
||||
* - 0 Success
|
||||
* - Other Fail
|
||||
*/
|
||||
int timer_irq_register(timer_device_number_t device, timer_channel_number_t channel, int is_single_shot, uint32_t priority, timer_callback_t callback, void *ctx);
|
||||
|
||||
/**
|
||||
* @brief Deregister timer interrupt user callback function
|
||||
*
|
||||
* @param[in] device The timer device number
|
||||
* @param[in] channel The channel
|
||||
*
|
||||
* @return result
|
||||
* - 0 Success
|
||||
* - Other Fail
|
||||
*/
|
||||
int timer_irq_unregister(timer_device_number_t device, timer_channel_number_t channel);
|
||||
|
||||
/**
|
||||
* @brief Enable timer
|
||||
*
|
||||
* @param[in] timer timer
|
||||
* @param[in] channel channel
|
||||
* @param[in] enable Enable or disable
|
||||
*
|
||||
*/
|
||||
void timer_set_enable(timer_device_number_t timer_number, timer_channel_number_t channel, uint32_t enable);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _DRIVER_TIMER_H */
|
||||
@@ -1,334 +0,0 @@
|
||||
/* Copyright 2018 Canaan Inc.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* http://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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief Universal Asynchronous Receiver/Transmitter (UART)
|
||||
*
|
||||
* The UART peripheral supports the following features:
|
||||
*
|
||||
* - 8-N-1 and 8-N-2 formats: 8 data bits, no parity bit, 1 start
|
||||
* bit, 1 or 2 stop bits
|
||||
*
|
||||
* - 8-entry transmit and receive FIFO buffers with programmable
|
||||
* watermark interrupts
|
||||
*
|
||||
* - 16× Rx oversampling with 2/3 majority voting per bit
|
||||
*
|
||||
* The UART peripheral does not support hardware flow control or
|
||||
* other modem control signals, or synchronous serial data
|
||||
* tranfesrs.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _DRIVER_APBUART_H
|
||||
#define _DRIVER_APBUART_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include "platform.h"
|
||||
#include "plic.h"
|
||||
#include "dmac.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef enum _uart_dev
|
||||
{
|
||||
UART_DEV1 = 0,
|
||||
UART_DEV2,
|
||||
UART_DEV3,
|
||||
} uart_dev_t;
|
||||
|
||||
typedef struct _uart
|
||||
{
|
||||
union
|
||||
{
|
||||
volatile uint32_t RBR;
|
||||
volatile uint32_t DLL;
|
||||
volatile uint32_t THR;
|
||||
};
|
||||
|
||||
union
|
||||
{
|
||||
volatile uint32_t DLH;
|
||||
volatile uint32_t IER;
|
||||
};
|
||||
|
||||
union
|
||||
{
|
||||
volatile uint32_t FCR;
|
||||
volatile uint32_t IIR;
|
||||
};
|
||||
|
||||
volatile uint32_t LCR;
|
||||
volatile uint32_t MCR;
|
||||
volatile uint32_t LSR;
|
||||
volatile uint32_t MSR;
|
||||
|
||||
volatile uint32_t SCR;
|
||||
volatile uint32_t LPDLL;
|
||||
volatile uint32_t LPDLH;
|
||||
|
||||
volatile uint32_t reserved1[2];
|
||||
|
||||
union
|
||||
{
|
||||
volatile uint32_t SRBR[16];
|
||||
volatile uint32_t STHR[16];
|
||||
};
|
||||
|
||||
volatile uint32_t FAR;
|
||||
volatile uint32_t TFR;
|
||||
volatile uint32_t RFW;
|
||||
volatile uint32_t USR;
|
||||
volatile uint32_t TFL;
|
||||
volatile uint32_t RFL;
|
||||
volatile uint32_t SRR;
|
||||
volatile uint32_t SRTS;
|
||||
volatile uint32_t SBCR;
|
||||
volatile uint32_t SDMAM;
|
||||
volatile uint32_t SFE;
|
||||
volatile uint32_t SRT;
|
||||
volatile uint32_t STET;
|
||||
volatile uint32_t HTX;
|
||||
volatile uint32_t DMASA;
|
||||
volatile uint32_t TCR;
|
||||
volatile uint32_t DE_EN;
|
||||
volatile uint32_t RE_EN;
|
||||
volatile uint32_t DET;
|
||||
volatile uint32_t TAT;
|
||||
volatile uint32_t DLF;
|
||||
volatile uint32_t RAR;
|
||||
volatile uint32_t TAR;
|
||||
volatile uint32_t LCR_EXT;
|
||||
volatile uint32_t reserved2[9];
|
||||
volatile uint32_t CPR;
|
||||
volatile uint32_t UCV;
|
||||
volatile uint32_t CTR;
|
||||
} uart_t;
|
||||
|
||||
typedef enum _uart_device_number
|
||||
{
|
||||
UART_DEVICE_1,
|
||||
UART_DEVICE_2,
|
||||
UART_DEVICE_3,
|
||||
UART_DEVICE_MAX,
|
||||
} uart_device_number_t;
|
||||
|
||||
typedef enum _uart_bitwidth
|
||||
{
|
||||
UART_BITWIDTH_5BIT = 5,
|
||||
UART_BITWIDTH_6BIT,
|
||||
UART_BITWIDTH_7BIT,
|
||||
UART_BITWIDTH_8BIT,
|
||||
} uart_bitwidth_t;
|
||||
|
||||
typedef enum _uart_stopbit
|
||||
{
|
||||
UART_STOP_1,
|
||||
UART_STOP_1_5,
|
||||
UART_STOP_2
|
||||
} uart_stopbit_t;
|
||||
|
||||
typedef enum _uart_rede_sel
|
||||
{
|
||||
DISABLE = 0,
|
||||
ENABLE,
|
||||
} uart_rede_sel_t;
|
||||
|
||||
typedef enum _uart_parity
|
||||
{
|
||||
UART_PARITY_NONE,
|
||||
UART_PARITY_ODD,
|
||||
UART_PARITY_EVEN
|
||||
} uart_parity_t;
|
||||
|
||||
typedef enum _uart_interrupt_mode
|
||||
{
|
||||
UART_SEND = 1,
|
||||
UART_RECEIVE = 2,
|
||||
} uart_interrupt_mode_t;
|
||||
|
||||
typedef enum _uart_send_trigger
|
||||
{
|
||||
UART_SEND_FIFO_0,
|
||||
UART_SEND_FIFO_2,
|
||||
UART_SEND_FIFO_4,
|
||||
UART_SEND_FIFO_8,
|
||||
} uart_send_trigger_t;
|
||||
|
||||
typedef enum _uart_receive_trigger
|
||||
{
|
||||
UART_RECEIVE_FIFO_1,
|
||||
UART_RECEIVE_FIFO_4,
|
||||
UART_RECEIVE_FIFO_8,
|
||||
UART_RECEIVE_FIFO_14,
|
||||
} uart_receive_trigger_t;
|
||||
|
||||
/**
|
||||
* @brief Send data from uart
|
||||
*
|
||||
* @param[in] channel Uart index
|
||||
* @param[in] buffer The data be transfer
|
||||
* @param[in] len The data length
|
||||
*
|
||||
* @return Transfer length
|
||||
*/
|
||||
int uart_send_data(uart_device_number_t channel, const char *buffer, size_t buf_len);
|
||||
|
||||
/**
|
||||
* @brief Read data from uart
|
||||
*
|
||||
* @param[in] channel Uart index
|
||||
* @param[in] buffer The Data received
|
||||
* @param[in] len Receive length
|
||||
*
|
||||
* @return Receive length
|
||||
*/
|
||||
int uart_receive_data(uart_device_number_t channel, char *buffer, size_t buf_len);
|
||||
|
||||
/**
|
||||
* @brief Init uart
|
||||
*
|
||||
* @param[in] channel Uart index
|
||||
*
|
||||
*/
|
||||
void uart_init(uart_device_number_t channel);
|
||||
|
||||
/**
|
||||
* @brief Set uart param
|
||||
*
|
||||
* @param[in] channel Uart index
|
||||
* @param[in] baud_rate Baudrate
|
||||
* @param[in] data_width Data width
|
||||
* @param[in] stopbit Stop bit
|
||||
* @param[in] parity Odd Even parity
|
||||
*
|
||||
*/
|
||||
void uart_config(uart_device_number_t channel, uint32_t baud_rate, uart_bitwidth_t data_width, uart_stopbit_t stopbit, uart_parity_t parity);
|
||||
|
||||
/**
|
||||
* @brief Set uart param
|
||||
*
|
||||
* @param[in] channel Uart index
|
||||
* @param[in] baud_rate Baudrate
|
||||
* @param[in] data_width Data width
|
||||
* @param[in] stopbit Stop bit
|
||||
* @param[in] parity Odd Even parity
|
||||
*
|
||||
*/
|
||||
void uart_configure(uart_device_number_t channel, uint32_t baud_rate, uart_bitwidth_t data_width, uart_stopbit_t stopbit, uart_parity_t parity);
|
||||
|
||||
/**
|
||||
* @brief Register uart interrupt
|
||||
*
|
||||
* @param[in] channel Uart index
|
||||
* @param[in] interrupt_mode Interrupt Mode receive or send
|
||||
* @param[in] uart_callback Call back
|
||||
* @param[in] ctx Param of call back
|
||||
* @param[in] priority Interrupt priority
|
||||
*
|
||||
*/
|
||||
void uart_irq_register(uart_device_number_t channel, uart_interrupt_mode_t interrupt_mode, plic_irq_callback_t uart_callback, void *ctx, uint32_t priority);
|
||||
|
||||
/**
|
||||
* @brief Deregister uart interrupt
|
||||
*
|
||||
* @param[in] channel Uart index
|
||||
* @param[in] interrupt_mode Interrupt Mode receive or send
|
||||
*
|
||||
*/
|
||||
void uart_irq_unregister(uart_device_number_t channel, uart_interrupt_mode_t interrupt_mode);
|
||||
|
||||
/**
|
||||
* @brief Set send interrupt threshold
|
||||
*
|
||||
* @param[in] channel Uart index
|
||||
* @param[in] trigger Threshold of send interrupt
|
||||
*
|
||||
*/
|
||||
void uart_set_send_trigger(uart_device_number_t channel, uart_send_trigger_t trigger);
|
||||
|
||||
/**
|
||||
* @brief Set receive interrupt threshold
|
||||
*
|
||||
* @param[in] channel Uart index
|
||||
* @param[in] trigger Threshold of receive interrupt
|
||||
*
|
||||
*/
|
||||
void uart_set_receive_trigger(uart_device_number_t channel, uart_receive_trigger_t trigger);
|
||||
|
||||
/**
|
||||
* @brief Send data by dma
|
||||
*
|
||||
* @param[in] channel Uart index
|
||||
* @param[in] dmac_channel Dmac channel
|
||||
* @param[in] buffer Send data
|
||||
* @param[in] buf_len Data length
|
||||
*
|
||||
*/
|
||||
void uart_send_data_dma(uart_device_number_t uart_channel, dmac_channel_number_t dmac_channel, const uint8_t *buffer, size_t buf_len);
|
||||
|
||||
/**
|
||||
* @brief Receive data by dma
|
||||
*
|
||||
* @param[in] channel Uart index
|
||||
* @param[in] dmac_channel Dmac channel
|
||||
* @param[in] buffer Receive data
|
||||
* @param[in] buf_len Data length
|
||||
*
|
||||
*/
|
||||
void uart_receive_data_dma(uart_device_number_t uart_channel, dmac_channel_number_t dmac_channel, uint8_t *buffer, size_t buf_len);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Send data by dma
|
||||
*
|
||||
* @param[in] uart_channel Uart index
|
||||
* @param[in] dmac_channel Dmac channel
|
||||
* @param[in] buffer Send data
|
||||
* @param[in] buf_len Data length
|
||||
* @param[in] uart_callback Call back
|
||||
* @param[in] ctx Param of call back
|
||||
* @param[in] priority Interrupt priority
|
||||
*
|
||||
*/
|
||||
void uart_send_data_dma_irq(uart_device_number_t uart_channel, dmac_channel_number_t dmac_channel,
|
||||
const uint8_t *buffer, size_t buf_len, plic_irq_callback_t uart_callback,
|
||||
void *ctx, uint32_t priority);
|
||||
|
||||
/**
|
||||
* @brief Receive data by dma
|
||||
*
|
||||
* @param[in] uart_channel Uart index
|
||||
* @param[in] dmac_channel Dmac channel
|
||||
* @param[in] buffer Receive data
|
||||
* @param[in] buf_len Data length
|
||||
* @param[in] uart_callback Call back
|
||||
* @param[in] ctx Param of call back
|
||||
* @param[in] priority Interrupt priority
|
||||
*
|
||||
*/
|
||||
void uart_receive_data_dma_irq(uart_device_number_t uart_channel, dmac_channel_number_t dmac_channel,
|
||||
uint8_t *buffer, size_t buf_len, plic_irq_callback_t uart_callback,
|
||||
void *ctx, uint32_t priority);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _DRIVER_APBUART_H */
|
||||
@@ -1,292 +0,0 @@
|
||||
/* Copyright 2018 Canaan Inc.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* http://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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief Universal Asynchronous Receiver/Transmitter (UART)
|
||||
*
|
||||
* The UART peripheral supports the following features:
|
||||
*
|
||||
* - 8-N-1 and 8-N-2 formats: 8 data bits, no parity bit, 1 start
|
||||
* bit, 1 or 2 stop bits
|
||||
*
|
||||
* - 8-entry transmit and receive FIFO buffers with programmable
|
||||
* watermark interrupts
|
||||
*
|
||||
* - 16× Rx oversampling with 2/3 majority voting per bit
|
||||
*
|
||||
* The UART peripheral does not support hardware flow control or
|
||||
* other modem control signals, or synchronous serial data
|
||||
* tranfesrs.
|
||||
*
|
||||
* @note UART RAM Layout
|
||||
*
|
||||
* | Address | Name | Description |
|
||||
* |-----------|----------|---------------------------------|
|
||||
* | 0x000 | txdata | Transmit data register |
|
||||
* | 0x004 | rxdata | Receive data register |
|
||||
* | 0x008 | txctrl | Transmit control register |
|
||||
* | 0x00C | rxctrl | Receive control register |
|
||||
* | 0x010 | ie | UART interrupt enable |
|
||||
* | 0x014 | ip | UART Interrupt pending |
|
||||
* | 0x018 | div | Baud rate divisor |
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _DRIVER_UARTHS_H
|
||||
#define _DRIVER_UARTHS_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include "platform.h"
|
||||
#include "plic.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* clang-format off */
|
||||
/* Register address offsets */
|
||||
#define UARTHS_REG_TXFIFO (0x00)
|
||||
#define UARTHS_REG_RXFIFO (0x04)
|
||||
#define UARTHS_REG_TXCTRL (0x08)
|
||||
#define UARTHS_REG_RXCTRL (0x0c)
|
||||
#define UARTHS_REG_IE (0x10)
|
||||
#define UARTHS_REG_IP (0x14)
|
||||
#define UARTHS_REG_DIV (0x18)
|
||||
|
||||
/* TXCTRL register */
|
||||
#define UARTHS_TXEN (0x01)
|
||||
#define UARTHS_TXWM(x) (((x) & 0xffff) << 16)
|
||||
|
||||
/* RXCTRL register */
|
||||
#define UARTHS_RXEN (0x01)
|
||||
#define UARTHS_RXWM(x) (((x) & 0xffff) << 16)
|
||||
|
||||
/* IP register */
|
||||
#define UARTHS_IP_TXWM (0x01)
|
||||
#define UARTHS_IP_RXWM (0x02)
|
||||
/* clang-format on */
|
||||
|
||||
typedef struct _uarths_txdata
|
||||
{
|
||||
/* Bits [7:0] is data */
|
||||
uint32_t data : 8;
|
||||
/* Bits [30:8] is 0 */
|
||||
uint32_t zero : 23;
|
||||
/* Bit 31 is full status */
|
||||
uint32_t full : 1;
|
||||
} __attribute__((packed, aligned(4))) uarths_txdata_t;
|
||||
|
||||
typedef struct _uarths_rxdata
|
||||
{
|
||||
/* Bits [7:0] is data */
|
||||
uint32_t data : 8;
|
||||
/* Bits [30:8] is 0 */
|
||||
uint32_t zero : 23;
|
||||
/* Bit 31 is empty status */
|
||||
uint32_t empty : 1;
|
||||
} __attribute__((packed, aligned(4))) uarths_rxdata_t;
|
||||
|
||||
typedef struct _uarths_txctrl
|
||||
{
|
||||
/* Bit 0 is txen, controls whether the Tx channel is active. */
|
||||
uint32_t txen : 1;
|
||||
/* Bit 1 is nstop, 0 for one stop bit and 1 for two stop bits */
|
||||
uint32_t nstop : 1;
|
||||
/* Bits [15:2] is reserved */
|
||||
uint32_t resv0 : 14;
|
||||
/* Bits [18:16] is threshold of interrupt triggers */
|
||||
uint32_t txcnt : 3;
|
||||
/* Bits [31:19] is reserved */
|
||||
uint32_t resv1 : 13;
|
||||
} __attribute__((packed, aligned(4))) uarths_txctrl_t;
|
||||
|
||||
typedef struct _uarths_rxctrl
|
||||
{
|
||||
/* Bit 0 is txen, controls whether the Tx channel is active. */
|
||||
uint32_t rxen : 1;
|
||||
/* Bits [15:1] is reserved */
|
||||
uint32_t resv0 : 15;
|
||||
/* Bits [18:16] is threshold of interrupt triggers */
|
||||
uint32_t rxcnt : 3;
|
||||
/* Bits [31:19] is reserved */
|
||||
uint32_t resv1 : 13;
|
||||
} __attribute__((packed, aligned(4))) uarths_rxctrl_t;
|
||||
|
||||
typedef struct _uarths_ip
|
||||
{
|
||||
/* Bit 0 is txwm, raised less than txcnt */
|
||||
uint32_t txwm : 1;
|
||||
/* Bit 1 is txwm, raised greater than rxcnt */
|
||||
uint32_t rxwm : 1;
|
||||
/* Bits [31:2] is 0 */
|
||||
uint32_t zero : 30;
|
||||
} __attribute__((packed, aligned(4))) uarths_ip_t;
|
||||
|
||||
typedef struct _uarths_ie
|
||||
{
|
||||
/* Bit 0 is txwm, raised less than txcnt */
|
||||
uint32_t txwm : 1;
|
||||
/* Bit 1 is txwm, raised greater than rxcnt */
|
||||
uint32_t rxwm : 1;
|
||||
/* Bits [31:2] is 0 */
|
||||
uint32_t zero : 30;
|
||||
} __attribute__((packed, aligned(4))) uarths_ie_t;
|
||||
|
||||
typedef struct _uarths_div
|
||||
{
|
||||
/* Bits [31:2] is baud rate divisor register */
|
||||
uint32_t div : 16;
|
||||
/* Bits [31:16] is 0 */
|
||||
uint32_t zero : 16;
|
||||
} __attribute__((packed, aligned(4))) uarths_div_t;
|
||||
|
||||
typedef struct _uarths
|
||||
{
|
||||
/* Address offset 0x00 */
|
||||
uarths_txdata_t txdata;
|
||||
/* Address offset 0x04 */
|
||||
uarths_rxdata_t rxdata;
|
||||
/* Address offset 0x08 */
|
||||
uarths_txctrl_t txctrl;
|
||||
/* Address offset 0x0c */
|
||||
uarths_rxctrl_t rxctrl;
|
||||
/* Address offset 0x10 */
|
||||
uarths_ie_t ie;
|
||||
/* Address offset 0x14 */
|
||||
uarths_ip_t ip;
|
||||
/* Address offset 0x18 */
|
||||
uarths_div_t div;
|
||||
} __attribute__((packed, aligned(4))) uarths_t;
|
||||
|
||||
typedef enum _uarths_interrupt_mode
|
||||
{
|
||||
UARTHS_SEND = 1,
|
||||
UARTHS_RECEIVE = 2,
|
||||
UARTHS_SEND_RECEIVE = 3,
|
||||
} uarths_interrupt_mode_t;
|
||||
|
||||
typedef enum _uarths_stopbit
|
||||
{
|
||||
UARTHS_STOP_1,
|
||||
UARTHS_STOP_2
|
||||
} uarths_stopbit_t;
|
||||
|
||||
extern volatile uarths_t *const uarths;
|
||||
|
||||
/**
|
||||
* @brief Initialization Core UART
|
||||
*
|
||||
* @return result
|
||||
* - 0 Success
|
||||
* - Other Fail
|
||||
*/
|
||||
void uarths_init(void);
|
||||
|
||||
/**
|
||||
* @brief Put a char to UART
|
||||
*
|
||||
* @param[in] c The char to put
|
||||
*
|
||||
* @note If c is '\n', a '\r' will be appended automatically
|
||||
*
|
||||
* @return result
|
||||
* - 0 Success
|
||||
* - Other Fail
|
||||
*/
|
||||
int uarths_putchar(char c);
|
||||
|
||||
/**
|
||||
* @brief Send a string to UART
|
||||
*
|
||||
* @param[in] s The string to send
|
||||
*
|
||||
* @note The string must ending with '\0'
|
||||
*
|
||||
* @return result
|
||||
* - 0 Success
|
||||
* - Other Fail
|
||||
*/
|
||||
int uarths_puts(const char *s);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Get a byte from UART
|
||||
*
|
||||
* @return byte as int type from UART
|
||||
*/
|
||||
int uarths_getc(void);
|
||||
|
||||
/**
|
||||
* @brief Set uarths interrupt callback
|
||||
*
|
||||
* @param[in] interrupt_mode Interrupt mode recevice or send
|
||||
* @param[in] uarths_callback Interrupt callback
|
||||
* @param[in] ctx Param of callback
|
||||
* @param[in] priority Interrupt priority
|
||||
*
|
||||
*/
|
||||
void uarths_set_irq(uarths_interrupt_mode_t interrupt_mode, plic_irq_callback_t uarths_callback, void *ctx, uint32_t priority);
|
||||
|
||||
/**
|
||||
* @brief Uarths receive data
|
||||
*
|
||||
* @param[in] buf The data received
|
||||
* @param[in] buf_len The length of data
|
||||
*
|
||||
* @return Number of received data
|
||||
*/
|
||||
size_t uarths_receive_data(uint8_t *buf, size_t buf_len);
|
||||
|
||||
/**
|
||||
* @brief Uarths receive data
|
||||
*
|
||||
* @param[in] buf The data sended
|
||||
* @param[in] buf_len The length of data
|
||||
*
|
||||
* @return Number of sended data
|
||||
*/
|
||||
size_t uarths_send_data(const uint8_t *buf, size_t buf_len);
|
||||
|
||||
/**
|
||||
* @brief Get interrupt mode
|
||||
*
|
||||
* @return Mode of interrupt
|
||||
*/
|
||||
uarths_interrupt_mode_t uarths_get_interrupt_mode(void);
|
||||
|
||||
/**
|
||||
* @brief Set uarths baud rate and stopbit
|
||||
*
|
||||
* @param[in] baud_rate The baud rate
|
||||
* @param[in] stopbit The stopbit of data
|
||||
*
|
||||
*/
|
||||
void uarths_config(uint32_t baud_rate, uarths_stopbit_t stopbit);
|
||||
|
||||
/**
|
||||
* @brief Set uart interrupt condition
|
||||
*
|
||||
* @param[in] interrupt_mode The interrupt mode
|
||||
* @param[in] cnt The count of tigger
|
||||
*
|
||||
*/
|
||||
void uarths_set_interrupt_cnt(uarths_interrupt_mode_t interrupt_mode, uint8_t cnt);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _DRIVER_UARTHS_H */
|
||||
@@ -1,347 +0,0 @@
|
||||
/* Copyright 2018 Canaan Inc.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* http://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 _DRIVER_UTILS_H
|
||||
#define _DRIVER_UTILS_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
#include <cstdbool>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#else /* __cplusplus */
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#define KENDRYTE_MIN(a, b) ((a) > (b) ? (b) : (a))
|
||||
#define KENDRYTE_MAX(a, b) ((a) > (b) ? (a) : (b))
|
||||
|
||||
#ifdef __ASSEMBLY__
|
||||
#define KENDRYTE_CAST(type, ptr) ptr
|
||||
#else /* __ASSEMBLY__ */
|
||||
/**
|
||||
* @brief Cast the pointer to specified pointer type.
|
||||
*
|
||||
* @param[in] type The pointer type to cast to
|
||||
* @param[in] ptr The pointer to apply the type cast to
|
||||
*/
|
||||
#define KENDRYTE_CAST(type, ptr) ((type)(ptr))
|
||||
#endif /* __ASSEMBLY__ */
|
||||
|
||||
/**
|
||||
* @addtogroup UTIL_RW_FUNC Memory Read/Write Utilities
|
||||
*
|
||||
* This section implements read and write functionality for various
|
||||
* memory untis. The memory unit terms used for these functions are
|
||||
* consistent with those used in the ARM Architecture Reference Manual
|
||||
* ARMv7-A and ARMv7-R edition manual. The terms used for units of memory are:
|
||||
*
|
||||
* Unit of Memory | Abbreviation | Size in Bits
|
||||
* :---------------|:-------------|:------------:
|
||||
* Byte | byte | 8
|
||||
* Half Word | hword | 16
|
||||
* Word | word | 32
|
||||
* Double Word | dword | 64
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Write the 8 bit byte to the destination address in device memory.
|
||||
*
|
||||
* @param[in] dest Write destination pointer address
|
||||
* @param[in] src 8 bit data byte to write to memory
|
||||
*/
|
||||
#define kendryte_write_byte(dest, src) \
|
||||
(*KENDRYTE_CAST(volatile uint8_t*, (dest)) = (src))
|
||||
|
||||
/**
|
||||
* @brief Read and return the 8 bit byte from the source address in device memory.
|
||||
*
|
||||
* @param[in] src Read source pointer address
|
||||
*
|
||||
* @return 8 bit data byte value
|
||||
*/
|
||||
#define kendryte_read_byte(src) (*KENDRYTE_CAST(volatile uint8_t*, (src)))
|
||||
|
||||
/**
|
||||
* @brief Write the 16 bit half word to the destination address in device memory.
|
||||
*
|
||||
* @param[in] dest Write destination pointer address
|
||||
* @param[in] src 16 bit data half word to write to memory
|
||||
*/
|
||||
#define kendryte_write_hword(dest, src) \
|
||||
(*KENDRYTE_CAST(volatile uint16_t*, (dest)) = (src))
|
||||
|
||||
/**
|
||||
* @brief Read and return the 16 bit half word from the source address in device
|
||||
*
|
||||
* @param[in] src Read source pointer address
|
||||
*
|
||||
* @return 16 bit data half word value
|
||||
*/
|
||||
#define kendryte_read_hword(src) (*KENDRYTE_CAST(volatile uint16_t*, (src)))
|
||||
|
||||
/**
|
||||
* @brief Write the 32 bit word to the destination address in device memory.
|
||||
*
|
||||
* @param[in] dest Write destination pointer address
|
||||
* @param[in] src 32 bit data word to write to memory
|
||||
*/
|
||||
#define kendryte_write_word(dest, src) \
|
||||
(*KENDRYTE_CAST(volatile uint32_t*, (dest)) = (src))
|
||||
|
||||
/**
|
||||
* @brief Read and return the 32 bit word from the source address in device memory.
|
||||
*
|
||||
* @param[in] src Read source pointer address
|
||||
*
|
||||
* @return 32 bit data half word value
|
||||
*/
|
||||
#define kendryte_read_word(src) (*KENDRYTE_CAST(volatile uint32_t*, (src)))
|
||||
|
||||
/**
|
||||
* @brief Write the 64 bit double word to the destination address in device memory.
|
||||
*
|
||||
* @param[in] dest Write destination pointer address
|
||||
* @param[in] src 64 bit data word to write to memory
|
||||
*/
|
||||
#define kendryte_write_dword(dest, src) \
|
||||
(*KENDRYTE_CAST(volatile uint64_t*, (dest)) = (src))
|
||||
|
||||
/**
|
||||
* @brief Read and return the 64 bit double word from the source address in device
|
||||
*
|
||||
* @param[in] src Read source pointer address
|
||||
*
|
||||
* @return 64 bit data half word value
|
||||
*/
|
||||
#define kendryte_read_dword(src) (*KENDRYTE_CAST(volatile uint64_t*, (src)))
|
||||
|
||||
/**
|
||||
* @brief Set selected bits in the 8 bit byte at the destination address in device
|
||||
*
|
||||
* @param[in] dest Destination pointer address
|
||||
* @param[in] bits Bits to set in destination byte
|
||||
*/
|
||||
#define kendryte_setbits_byte(dest, bits) \
|
||||
(kendryte_write_byte(dest, kendryte_read_byte(dest) | (bits)))
|
||||
|
||||
/**
|
||||
* @brief Clear selected bits in the 8 bit byte at the destination address in device
|
||||
*
|
||||
* @param[in] dest Destination pointer address
|
||||
* @param[in] bits Bits to clear in destination byte
|
||||
*/
|
||||
#define kendryte_clrbits_byte(dest, bits) \
|
||||
(kendryte_write_byte(dest, kendryte_read_byte(dest) & ~(bits)))
|
||||
|
||||
/**
|
||||
* @brief Change or toggle selected bits in the 8 bit byte at the destination address
|
||||
*
|
||||
* @param[in] dest Destination pointer address
|
||||
* @param[in] bits Bits to change in destination byte
|
||||
*/
|
||||
#define kendryte_xorbits_byte(dest, bits) \
|
||||
(kendryte_write_byte(dest, kendryte_read_byte(dest) ^ (bits)))
|
||||
|
||||
/**
|
||||
* @brief Replace selected bits in the 8 bit byte at the destination address in device
|
||||
*
|
||||
* @param[in] dest Destination pointer address
|
||||
* @param[in] msk Bits to replace in destination byte
|
||||
* @param[in] src Source bits to write to cleared bits in destination byte
|
||||
*/
|
||||
#define kendryte_replbits_byte(dest, msk, src) \
|
||||
(kendryte_write_byte(dest, (kendryte_read_byte(dest) & ~(msk)) | ((src) & (msk))))
|
||||
|
||||
/**
|
||||
* @brief Set selected bits in the 16 bit halfword at the destination address in
|
||||
*
|
||||
* @param[in] dest Destination pointer address
|
||||
* @param[in] bits Bits to set in destination halfword
|
||||
*/
|
||||
#define kendryte_setbits_hword(dest, bits) \
|
||||
(kendryte_write_hword(dest, kendryte_read_hword(dest) | (bits)))
|
||||
|
||||
/**
|
||||
* @brief Clear selected bits in the 16 bit halfword at the destination address in
|
||||
*
|
||||
* @param[in] dest Destination pointer address
|
||||
* @param[in] bits Bits to clear in destination halfword
|
||||
*/
|
||||
#define kendryte_clrbits_hword(dest, bits) \
|
||||
(kendryte_write_hword(dest, kendryte_read_hword(dest) & ~(bits)))
|
||||
|
||||
/**
|
||||
* @brief Change or toggle selected bits in the 16 bit halfword at the destination
|
||||
*
|
||||
* @param[in] dest Destination pointer address
|
||||
* @param[in] bits Bits to change in destination halfword
|
||||
*/
|
||||
#define kendryte_xorbits_hword(dest, bits) \
|
||||
(kendryte_write_hword(dest, kendryte_read_hword(dest) ^ (bits)))
|
||||
|
||||
/**
|
||||
* @brief Replace selected bits in the 16 bit halfword at the destination address in
|
||||
*
|
||||
* @param[in] dest Destination pointer address
|
||||
* @param[in] msk Bits to replace in destination byte
|
||||
* @param[in] src Source bits to write to cleared bits in destination halfword
|
||||
*/
|
||||
#define kendryte_replbits_hword(dest, msk, src) \
|
||||
(kendryte_write_hword(dest, (kendryte_read_hword(dest) & ~(msk)) | ((src) & (msk))))
|
||||
|
||||
/**
|
||||
* @brief Set selected bits in the 32 bit word at the destination address in device
|
||||
*
|
||||
* @param[in] dest Destination pointer address
|
||||
* @param[in] bits Bits to set in destination word
|
||||
*/
|
||||
#define kendryte_setbits_word(dest, bits) \
|
||||
(kendryte_write_word(dest, kendryte_read_word(dest) | (bits)))
|
||||
|
||||
/**
|
||||
* @brief Clear selected bits in the 32 bit word at the destination address in device
|
||||
*
|
||||
* @param[in] dest Destination pointer address
|
||||
* @param[in] bits Bits to clear in destination word
|
||||
*/
|
||||
#define kendryte_clrbits_word(dest, bits) \
|
||||
(kendryte_write_word(dest, kendryte_read_word(dest) & ~(bits)))
|
||||
|
||||
/**
|
||||
* @brief Change or toggle selected bits in the 32 bit word at the destination address
|
||||
*
|
||||
* @param[in] dest Destination pointer address
|
||||
* @param[in] bits Bits to change in destination word
|
||||
*/
|
||||
#define kendryte_xorbits_word(dest, bits) \
|
||||
(kendryte_write_word(dest, kendryte_read_word(dest) ^ (bits)))
|
||||
|
||||
/**
|
||||
* @brief Replace selected bits in the 32 bit word at the destination address in
|
||||
*
|
||||
* @param[in] dest Destination pointer address
|
||||
* @param[in] msk Bits to replace in destination word
|
||||
* @param[in] src Source bits to write to cleared bits in destination word
|
||||
*/
|
||||
#define kendryte_replbits_word(dest, msk, src) \
|
||||
(kendryte_write_word(dest, (kendryte_read_word(dest) & ~(msk)) | ((src) & (msk))))
|
||||
|
||||
/**
|
||||
* @brief Set selected bits in the 64 bit doubleword at the destination address in
|
||||
*
|
||||
* @param[in] dest Destination pointer address
|
||||
* @param[in] bits Bits to set in destination doubleword
|
||||
*/
|
||||
#define kendryte_setbits_dword(dest, bits) \
|
||||
(kendryte_write_dword(dest, kendryte_read_dword(dest) | (bits)))
|
||||
|
||||
/**
|
||||
* @brief Clear selected bits in the 64 bit doubleword at the destination address in
|
||||
*
|
||||
* @param[in] dest Destination pointer address
|
||||
* @param[in] bits Bits to clear in destination doubleword
|
||||
*/
|
||||
#define kendryte_clrbits_dword(dest, bits) \
|
||||
(kendryte_write_dword(dest, kendryte_read_dword(dest) & ~(bits)))
|
||||
|
||||
/**
|
||||
* @brief Change or toggle selected bits in the 64 bit doubleword at the destination
|
||||
*
|
||||
* @param[in] dest Destination pointer address
|
||||
* @param[in] bits Bits to change in destination doubleword
|
||||
*/
|
||||
#define kendryte_xorbits_dword(dest, bits) \
|
||||
(kendryte_write_dword(dest, kendryte_read_dword(dest) ^ (bits)))
|
||||
|
||||
/**
|
||||
* @brief Replace selected bits in the 64 bit doubleword at the destination address in
|
||||
*
|
||||
* @param[in] dest Destination pointer address
|
||||
* @param[in] msk its to replace in destination doubleword
|
||||
* @param[in] src Source bits to write to cleared bits in destination word
|
||||
*/
|
||||
#define kendryte_replbits_dword(dest, msk, src) \
|
||||
(kendryte_write_dword(dest, (kendryte_read_dword(dest) & ~(msk)) | ((src) & (msk))))
|
||||
|
||||
#define configASSERT(x) \
|
||||
if ((x) == 0) \
|
||||
{ \
|
||||
printf("(%s:%d) %s\r\n", __FILE__, __LINE__, #x); \
|
||||
for (;;) \
|
||||
; \
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set value by mask
|
||||
*
|
||||
* @param[in] bits The one be set
|
||||
* @param[in] mask mask value
|
||||
* @param[in] value The value to set
|
||||
*/
|
||||
void set_bit(volatile uint32_t *bits, uint32_t mask, uint32_t value);
|
||||
|
||||
/**
|
||||
* @brief Set value by mask
|
||||
*
|
||||
* @param[in] bits The one be set
|
||||
* @param[in] mask Mask value
|
||||
* @param[in] offset Mask's offset
|
||||
* @param[in] value The value to set
|
||||
*/
|
||||
void set_bit_offset(volatile uint32_t *bits, uint32_t mask, size_t offset, uint32_t value);
|
||||
|
||||
/**
|
||||
* @brief Set bit for gpio, only set one bit
|
||||
*
|
||||
* @param[in] bits The one be set
|
||||
* @param[in] idx Offset value
|
||||
* @param[in] value The value to set
|
||||
*/
|
||||
void set_gpio_bit(volatile uint32_t *bits, size_t idx, uint32_t value);
|
||||
|
||||
/**
|
||||
* @brief Get bits value of mask
|
||||
*
|
||||
* @param[in] bits The source data
|
||||
* @param[in] mask Mask value
|
||||
* @param[in] offset Mask's offset
|
||||
*
|
||||
* @return The bits value of mask
|
||||
*/
|
||||
uint32_t get_bit(volatile uint32_t *bits, uint32_t mask, size_t offset);
|
||||
|
||||
/**
|
||||
* @brief Get a bit value by offset
|
||||
*
|
||||
* @param[in] bits The source data
|
||||
* @param[in] offset Bit's offset
|
||||
*
|
||||
*
|
||||
* @return The bit value
|
||||
*/
|
||||
uint32_t get_gpio_bit(volatile uint32_t *bits, size_t offset);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
#endif /* _DRIVER_COMMON_H */
|
||||
|
||||
@@ -1,170 +0,0 @@
|
||||
/* Copyright 2018 Canaan Inc.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* http://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 _DRIVER_WDT_H
|
||||
#define _DRIVER_WDT_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <plic.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* clang-format off */
|
||||
typedef struct _wdt
|
||||
{
|
||||
/* WDT Control Register (0x00) */
|
||||
volatile uint32_t cr;
|
||||
/* WDT Timeout Range Register (0x04) */
|
||||
volatile uint32_t torr;
|
||||
/* WDT Current Counter Value Register (0x08) */
|
||||
volatile uint32_t ccvr;
|
||||
/* WDT Counter Restart Register (0x0c) */
|
||||
volatile uint32_t crr;
|
||||
/* WDT Interrupt Status Register (0x10) */
|
||||
volatile uint32_t stat;
|
||||
/* WDT Interrupt Clear Register (0x14) */
|
||||
volatile uint32_t eoi;
|
||||
/* reserverd (0x18) */
|
||||
volatile uint32_t resv1;
|
||||
/* WDT Protection level Register (0x1c) */
|
||||
volatile uint32_t prot_level;
|
||||
/* reserved (0x20-0xe0) */
|
||||
volatile uint32_t resv4[49];
|
||||
/* WDT Component Parameters Register 5 (0xe4) */
|
||||
volatile uint32_t comp_param_5;
|
||||
/* WDT Component Parameters Register 4 (0xe8) */
|
||||
volatile uint32_t comp_param_4;
|
||||
/* WDT Component Parameters Register 3 (0xec) */
|
||||
volatile uint32_t comp_param_3;
|
||||
/* WDT Component Parameters Register 2 (0xf0) */
|
||||
volatile uint32_t comp_param_2;
|
||||
/* WDT Component Parameters Register 1 (0xf4) */
|
||||
volatile uint32_t comp_param_1;
|
||||
/* WDT Component Version Register (0xf8) */
|
||||
volatile uint32_t comp_version;
|
||||
/* WDT Component Type Register (0xfc) */
|
||||
volatile uint32_t comp_type;
|
||||
} __attribute__((packed, aligned(4))) wdt_t;
|
||||
|
||||
typedef enum _wdt_device_number
|
||||
{
|
||||
WDT_DEVICE_0,
|
||||
WDT_DEVICE_1,
|
||||
WDT_DEVICE_MAX,
|
||||
} wdt_device_number_t;
|
||||
|
||||
|
||||
#define WDT_RESET_ALL 0x00000000U
|
||||
#define WDT_RESET_CPU 0x00000001U
|
||||
|
||||
/* WDT Control Register */
|
||||
#define WDT_CR_ENABLE 0x00000001U
|
||||
#define WDT_CR_RMOD_MASK 0x00000002U
|
||||
#define WDT_CR_RMOD_RESET 0x00000000U
|
||||
#define WDT_CR_RMOD_INTERRUPT 0x00000002U
|
||||
#define WDT_CR_RPL_MASK 0x0000001CU
|
||||
#define WDT_CR_RPL(x) ((x) << 2)
|
||||
/* WDT Timeout Range Register */
|
||||
#define WDT_TORR_TOP_MASK 0x000000FFU
|
||||
#define WDT_TORR_TOP(x) ((x) << 4 | (x) << 0)
|
||||
/* WDT Current Counter Value Register */
|
||||
#define WDT_CCVR_MASK 0xFFFFFFFFU
|
||||
/* WDT Counter Restart Register */
|
||||
#define WDT_CRR_MASK 0x00000076U
|
||||
/* WDT Interrupt Status Register */
|
||||
#define WDT_STAT_MASK 0x00000001U
|
||||
/* WDT Interrupt Clear Register */
|
||||
#define WDT_EOI_MASK 0x00000001U
|
||||
/* WDT Protection level Register */
|
||||
#define WDT_PROT_LEVEL_MASK 0x00000007U
|
||||
/* WDT Component Parameter Register 5 */
|
||||
#define WDT_COMP_PARAM_5_CP_WDT_USER_TOP_MAX_MASK 0xFFFFFFFFU
|
||||
/* WDT Component Parameter Register 4 */
|
||||
#define WDT_COMP_PARAM_4_CP_WDT_USER_TOP_INIT_MAX_MASK 0xFFFFFFFFU
|
||||
/* WDT Component Parameter Register 3 */
|
||||
#define WDT_COMP_PARAM_3_CD_WDT_TOP_RST_MASK 0xFFFFFFFFU
|
||||
/* WDT Component Parameter Register 2 */
|
||||
#define WDT_COMP_PARAM_3_CP_WDT_CNT_RST_MASK 0xFFFFFFFFU
|
||||
/* WDT Component Parameter Register 1 */
|
||||
#define WDT_COMP_PARAM_1_WDT_ALWAYS_EN_MASK 0x00000001U
|
||||
#define WDT_COMP_PARAM_1_WDT_DFLT_RMOD_MASK 0x00000002U
|
||||
#define WDT_COMP_PARAM_1_WDT_DUAL_TOP_MASK 0x00000004U
|
||||
#define WDT_COMP_PARAM_1_WDT_HC_RMOD_MASK 0x00000008U
|
||||
#define WDT_COMP_PARAM_1_WDT_HC_RPL_MASK 0x00000010U
|
||||
#define WDT_COMP_PARAM_1_WDT_HC_TOP_MASK 0x00000020U
|
||||
#define WDT_COMP_PARAM_1_WDT_USE_FIX_TOP_MASK 0x00000040U
|
||||
#define WDT_COMP_PARAM_1_WDT_PAUSE_MASK 0x00000080U
|
||||
#define WDT_COMP_PARAM_1_APB_DATA_WIDTH_MASK 0x00000300U
|
||||
#define WDT_COMP_PARAM_1_WDT_DFLT_RPL_MASK 0x00001C00U
|
||||
#define WDT_COMP_PARAM_1_WDT_DFLT_TOP_MASK 0x000F0000U
|
||||
#define WDT_COMP_PARAM_1_WDT_DFLT_TOP_INIT_MASK 0x00F00000U
|
||||
#define WDT_COMP_PARAM_1_WDT_CNT_WIDTH_MASK 0x1F000000U
|
||||
/* WDT Component Version Register */
|
||||
#define WDT_COMP_VERSION_MASK 0xFFFFFFFFU
|
||||
/* WDT Component Type Register */
|
||||
#define WDT_COMP_TYPE_MASK 0xFFFFFFFFU
|
||||
/* clang-format on */
|
||||
|
||||
/**
|
||||
* @brief Feed wdt
|
||||
*/
|
||||
void wdt_feed(wdt_device_number_t id);
|
||||
|
||||
/**
|
||||
* @brief Start wdt
|
||||
*
|
||||
* @param[in] id Wdt id 0 or 1
|
||||
* @param[in] time_out_ms Wdt trigger time
|
||||
* @param[in] on_irq Wdt interrupt callback
|
||||
*
|
||||
*/
|
||||
void wdt_start(wdt_device_number_t id, uint64_t time_out_ms, plic_irq_callback_t on_irq);
|
||||
|
||||
/**
|
||||
* @brief Start wdt
|
||||
*
|
||||
* @param[in] id Wdt id 0 or 1
|
||||
* @param[in] time_out_ms Wdt trigger time
|
||||
* @param[in] on_irq Wdt interrupt callback
|
||||
* @param[in] ctx Param of callback
|
||||
*
|
||||
* @return Wdt time
|
||||
*
|
||||
*/
|
||||
uint32_t wdt_init(wdt_device_number_t id, uint64_t time_out_ms, plic_irq_callback_t on_irq, void *ctx);
|
||||
|
||||
/**
|
||||
* @brief Stop wdt
|
||||
*
|
||||
* @param[in] id Wdt id 0 or 1
|
||||
*
|
||||
*/
|
||||
void wdt_stop(wdt_device_number_t id);
|
||||
|
||||
/**
|
||||
* @brief Clear wdt interrupt
|
||||
*
|
||||
* @param[in] id Wdt id 0 or 1
|
||||
*
|
||||
*/
|
||||
void wdt_clear_interrupt(wdt_device_number_t id);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _DRIVER_WDT_H */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,209 +0,0 @@
|
||||
/* Copyright 2018 Canaan Inc.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* http://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.
|
||||
*/
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include "encoding.h"
|
||||
#include "plic.h"
|
||||
#include "syscalls.h"
|
||||
#include "syslog.h"
|
||||
|
||||
volatile plic_t* const plic = (volatile plic_t*)PLIC_BASE_ADDR;
|
||||
|
||||
static plic_instance_t plic_instance[PLIC_NUM_CORES][IRQN_MAX];
|
||||
|
||||
void plic_init(void)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
/* Get current core id */
|
||||
unsigned long core_id = current_coreid();
|
||||
|
||||
/* Disable all interrupts for the current core. */
|
||||
for (i = 0; i < ((PLIC_NUM_SOURCES + 32u) / 32u); i++)
|
||||
plic->target_enables.target[core_id].enable[i] = 0;
|
||||
|
||||
static uint8_t s_plic_priorities_init_flag = 0;
|
||||
/* Set priorities to zero. */
|
||||
if(s_plic_priorities_init_flag == 0)
|
||||
{
|
||||
for (i = 0; i < PLIC_NUM_SOURCES; i++)
|
||||
plic->source_priorities.priority[i] = 0;
|
||||
s_plic_priorities_init_flag = 1;
|
||||
}
|
||||
|
||||
/* Set the threshold to zero. */
|
||||
plic->targets.target[core_id].priority_threshold = 0;
|
||||
|
||||
/* Clear PLIC instance for every cores */
|
||||
for (i = 0; i < IRQN_MAX; i++)
|
||||
{
|
||||
/* clang-format off */
|
||||
plic_instance[core_id][i] = (const plic_instance_t){
|
||||
.callback = NULL,
|
||||
.ctx = NULL,
|
||||
};
|
||||
/* clang-format on */
|
||||
}
|
||||
|
||||
/*
|
||||
* A successful claim will also atomically clear the corresponding
|
||||
* pending bit on the interrupt source. A target can perform a claim
|
||||
* at any time, even if the EIP is not set.
|
||||
*/
|
||||
i = 0;
|
||||
while (plic->targets.target[core_id].claim_complete > 0 && i < 100)
|
||||
{
|
||||
/* This loop will clear pending bit on the interrupt source */
|
||||
i++;
|
||||
}
|
||||
|
||||
/* Enable machine external interrupts. */
|
||||
set_csr(mie, MIP_MEIP);
|
||||
}
|
||||
|
||||
int plic_irq_enable(plic_irq_t irq_number)
|
||||
{
|
||||
/* Check parameters */
|
||||
if (PLIC_NUM_SOURCES < irq_number || 0 > irq_number)
|
||||
return -1;
|
||||
unsigned long core_id = current_coreid();
|
||||
/* Get current enable bit array by IRQ number */
|
||||
uint32_t current = plic->target_enables.target[core_id].enable[irq_number / 32];
|
||||
/* Set enable bit in enable bit array */
|
||||
current |= (uint32_t)1 << (irq_number % 32);
|
||||
/* Write back the enable bit array */
|
||||
plic->target_enables.target[core_id].enable[irq_number / 32] = current;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int plic_irq_disable(plic_irq_t irq_number)
|
||||
{
|
||||
/* Check parameters */
|
||||
if (PLIC_NUM_SOURCES < irq_number || 0 > irq_number)
|
||||
return -1;
|
||||
unsigned long core_id = current_coreid();
|
||||
/* Get current enable bit array by IRQ number */
|
||||
uint32_t current = plic->target_enables.target[core_id].enable[irq_number / 32];
|
||||
/* Clear enable bit in enable bit array */
|
||||
current &= ~((uint32_t)1 << (irq_number % 32));
|
||||
/* Write back the enable bit array */
|
||||
plic->target_enables.target[core_id].enable[irq_number / 32] = current;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int plic_set_priority(plic_irq_t irq_number, uint32_t priority)
|
||||
{
|
||||
/* Check parameters */
|
||||
if (PLIC_NUM_SOURCES < irq_number || 0 > irq_number)
|
||||
return -1;
|
||||
/* Set interrupt priority by IRQ number */
|
||||
plic->source_priorities.priority[irq_number] = priority;
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t plic_get_priority(plic_irq_t irq_number)
|
||||
{
|
||||
/* Check parameters */
|
||||
if (PLIC_NUM_SOURCES < irq_number || 0 > irq_number)
|
||||
return 0;
|
||||
/* Get interrupt priority by IRQ number */
|
||||
return plic->source_priorities.priority[irq_number];
|
||||
}
|
||||
|
||||
uint32_t plic_irq_claim(void)
|
||||
{
|
||||
unsigned long core_id = current_coreid();
|
||||
/* Perform IRQ claim */
|
||||
return plic->targets.target[core_id].claim_complete;
|
||||
}
|
||||
|
||||
int plic_irq_complete(uint32_t source)
|
||||
{
|
||||
unsigned long core_id = current_coreid();
|
||||
/* Perform IRQ complete */
|
||||
plic->targets.target[core_id].claim_complete = source;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void plic_irq_register(plic_irq_t irq, plic_irq_callback_t callback, void *ctx)
|
||||
{
|
||||
/* Read core id */
|
||||
unsigned long core_id = current_coreid();
|
||||
/* Set user callback function */
|
||||
plic_instance[core_id][irq].callback = callback;
|
||||
/* Assign user context */
|
||||
plic_instance[core_id][irq].ctx = ctx;
|
||||
}
|
||||
|
||||
void plic_irq_unregister(plic_irq_t irq)
|
||||
{
|
||||
/* Just assign NULL to user callback function and context */
|
||||
plic_irq_register(irq, NULL, NULL);
|
||||
}
|
||||
|
||||
void __attribute__((weak, alias("plic_irq_unregister"))) plic_irq_deregister(plic_irq_t irq);
|
||||
|
||||
plic_instance_t (*plic_get_instance(void))[IRQN_MAX]
|
||||
{
|
||||
return plic_instance;
|
||||
}
|
||||
|
||||
/*Entry Point for PLIC Interrupt Handler*/
|
||||
uintptr_t __attribute__((weak))
|
||||
handle_irq_m_ext(uintptr_t cause, uintptr_t epc)
|
||||
{
|
||||
/*
|
||||
* After the highest-priority pending interrupt is claimed by a target
|
||||
* and the corresponding IP bit is cleared, other lower-priority
|
||||
* pending interrupts might then become visible to the target, and so
|
||||
* the PLIC EIP bit might not be cleared after a claim. The interrupt
|
||||
* handler can check the local meip/heip/seip/ueip bits before exiting
|
||||
* the handler, to allow more efficient service of other interrupts
|
||||
* without first restoring the interrupted context and taking another
|
||||
* interrupt trap.
|
||||
*/
|
||||
if (read_csr(mip) & MIP_MEIP)
|
||||
{
|
||||
/* Get current core id */
|
||||
uint64_t core_id = current_coreid();
|
||||
/* Get primitive interrupt enable flag */
|
||||
uint64_t ie_flag = read_csr(mie);
|
||||
/* Get current IRQ num */
|
||||
uint32_t int_num = plic->targets.target[core_id].claim_complete;
|
||||
/* Get primitive IRQ threshold */
|
||||
uint32_t int_threshold = plic->targets.target[core_id].priority_threshold;
|
||||
/* Set new IRQ threshold = current IRQ threshold */
|
||||
plic->targets.target[core_id].priority_threshold = plic->source_priorities.priority[int_num];
|
||||
/* Disable software interrupt and timer interrupt */
|
||||
clear_csr(mie, MIP_MTIP | MIP_MSIP);
|
||||
/* Enable global interrupt */
|
||||
set_csr(mstatus, MSTATUS_MIE);
|
||||
if (plic_instance[core_id][int_num].callback)
|
||||
plic_instance[core_id][int_num].callback(
|
||||
plic_instance[core_id][int_num].ctx);
|
||||
/* Perform IRQ complete */
|
||||
plic->targets.target[core_id].claim_complete = int_num;
|
||||
/* Disable global interrupt */
|
||||
clear_csr(mstatus, MSTATUS_MIE);
|
||||
/* Set MPIE and MPP flag used to MRET instructions restore MIE flag */
|
||||
set_csr(mstatus, MSTATUS_MPIE | MSTATUS_MPP);
|
||||
/* Restore primitive interrupt enable flag */
|
||||
write_csr(mie, ie_flag);
|
||||
/* Restore primitive IRQ threshold */
|
||||
plic->targets.target[core_id].priority_threshold = int_threshold;
|
||||
}
|
||||
|
||||
return epc;
|
||||
}
|
||||
@@ -1,58 +0,0 @@
|
||||
/* Copyright 2018 Canaan Inc.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* http://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.
|
||||
*/
|
||||
#include "timer.h"
|
||||
#include "pwm.h"
|
||||
#include "sysctl.h"
|
||||
#include <stddef.h>
|
||||
#include "utils.h"
|
||||
#include "plic.h"
|
||||
#include "io.h"
|
||||
|
||||
void pwm_init(pwm_device_number_t pwm_number)
|
||||
{
|
||||
sysctl_clock_enable(SYSCTL_CLOCK_TIMER0 + pwm_number);
|
||||
}
|
||||
|
||||
void pwm_set_enable(pwm_device_number_t pwm_number, pwm_channel_number_t channel, int enable)
|
||||
{
|
||||
if (enable)
|
||||
{
|
||||
if (timer[pwm_number]->channel[channel].load_count == 0)
|
||||
timer[pwm_number]->channel[channel].load_count = 1;
|
||||
if (timer[pwm_number]->load_count2[channel] == 0)
|
||||
timer[pwm_number]->load_count2[channel] = 1;
|
||||
timer[pwm_number]->channel[channel].control = TIMER_CR_INTERRUPT_MASK | TIMER_CR_PWM_ENABLE | TIMER_CR_USER_MODE | TIMER_CR_ENABLE;
|
||||
}
|
||||
else
|
||||
{
|
||||
timer[pwm_number]->channel[channel].control = TIMER_CR_INTERRUPT_MASK;
|
||||
}
|
||||
}
|
||||
|
||||
double pwm_set_frequency(pwm_device_number_t pwm_number, pwm_channel_number_t channel, double frequency, double duty)
|
||||
{
|
||||
uint32_t clk_freq = sysctl_clock_get_freq(SYSCTL_CLOCK_TIMER0 + pwm_number);
|
||||
|
||||
int32_t periods = (int32_t)(clk_freq / frequency);
|
||||
configASSERT(periods > 0 && periods <= INT32_MAX);
|
||||
frequency = clk_freq / (double)periods;
|
||||
|
||||
uint32_t percent = (uint32_t)(duty * periods);
|
||||
timer[pwm_number]->channel[channel].load_count = periods - percent;
|
||||
timer[pwm_number]->load_count2[channel] = percent;
|
||||
|
||||
return frequency;
|
||||
}
|
||||
|
||||
@@ -1,587 +0,0 @@
|
||||
/* Copyright 2018 Canaan Inc.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* http://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.
|
||||
*/
|
||||
#include <stdint.h>
|
||||
#include <time.h>
|
||||
#include <stdlib.h>
|
||||
#include "encoding.h"
|
||||
#include "sysctl.h"
|
||||
#include "rtc.h"
|
||||
|
||||
volatile rtc_t *const rtc = (volatile rtc_t *)RTC_BASE_ADDR;
|
||||
|
||||
struct tm rtc_date_time;
|
||||
|
||||
void rtc_timer_set_mode(rtc_timer_mode_t timer_mode)
|
||||
{
|
||||
rtc_register_ctrl_t register_ctrl = rtc->register_ctrl;
|
||||
|
||||
switch (timer_mode)
|
||||
{
|
||||
case RTC_TIMER_PAUSE:
|
||||
register_ctrl.read_enable = 0;
|
||||
register_ctrl.write_enable = 0;
|
||||
break;
|
||||
case RTC_TIMER_RUNNING:
|
||||
register_ctrl.read_enable = 1;
|
||||
register_ctrl.write_enable = 0;
|
||||
break;
|
||||
case RTC_TIMER_SETTING:
|
||||
register_ctrl.read_enable = 0;
|
||||
register_ctrl.write_enable = 1;
|
||||
break;
|
||||
default:
|
||||
register_ctrl.read_enable = 0;
|
||||
register_ctrl.write_enable = 0;
|
||||
break;
|
||||
}
|
||||
rtc->register_ctrl = register_ctrl;
|
||||
}
|
||||
|
||||
rtc_timer_mode_t rtc_timer_get_mode(void)
|
||||
{
|
||||
rtc_register_ctrl_t register_ctrl = rtc->register_ctrl;
|
||||
rtc_timer_mode_t timer_mode = RTC_TIMER_PAUSE;
|
||||
|
||||
if ((!register_ctrl.read_enable) && (!register_ctrl.write_enable))
|
||||
{
|
||||
/* RTC_TIMER_PAUSE */
|
||||
timer_mode = RTC_TIMER_PAUSE;
|
||||
}
|
||||
else if ((register_ctrl.read_enable) && (!register_ctrl.write_enable))
|
||||
{
|
||||
/* RTC_TIMER_RUNNING */
|
||||
timer_mode = RTC_TIMER_RUNNING;
|
||||
}
|
||||
else if ((!register_ctrl.read_enable) && (register_ctrl.write_enable)) {
|
||||
/* RTC_TIMER_SETTING */
|
||||
timer_mode = RTC_TIMER_SETTING;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Something is error, reset timer mode */
|
||||
rtc_timer_set_mode(timer_mode);
|
||||
}
|
||||
|
||||
return timer_mode;
|
||||
}
|
||||
|
||||
static inline int rtc_in_range(int value, int min, int max)
|
||||
{
|
||||
return ((value >= min) && (value <= max));
|
||||
}
|
||||
|
||||
int rtc_timer_set_tm(const struct tm *tm)
|
||||
{
|
||||
rtc_date_t timer_date;
|
||||
rtc_time_t timer_time;
|
||||
rtc_extended_t timer_extended;
|
||||
|
||||
if (tm)
|
||||
{
|
||||
/*
|
||||
* Range of tm->tm_sec could be [0,61]
|
||||
*
|
||||
* Range of tm->tm_sec allows for a positive leap second. Two
|
||||
* leap seconds in the same minute are not allowed (the C90
|
||||
* range 0..61 was a defect)
|
||||
*/
|
||||
if (rtc_in_range(tm->tm_sec, 0, 59))
|
||||
timer_time.second = tm->tm_sec;
|
||||
else
|
||||
return -1;
|
||||
|
||||
/* Range of tm->tm_min could be [0,59] */
|
||||
if (rtc_in_range(tm->tm_min, 0, 59))
|
||||
timer_time.minute = tm->tm_min;
|
||||
else
|
||||
return -1;
|
||||
|
||||
/* Range of tm->tm_hour could be [0, 23] */
|
||||
if (rtc_in_range(tm->tm_hour, 0, 23))
|
||||
timer_time.hour = tm->tm_hour;
|
||||
else
|
||||
return -1;
|
||||
|
||||
/* Range of tm->tm_mday could be [1, 31] */
|
||||
if (rtc_in_range(tm->tm_mday, 1, 31))
|
||||
timer_date.day = tm->tm_mday;
|
||||
else
|
||||
return -1;
|
||||
|
||||
/*
|
||||
* Range of tm->tm_mon could be [0, 11]
|
||||
* But in this RTC, date.month should be [1, 12]
|
||||
*/
|
||||
if (rtc_in_range(tm->tm_mon, 0, 11))
|
||||
timer_date.month = tm->tm_mon + 1;
|
||||
else
|
||||
return -1;
|
||||
|
||||
/*
|
||||
* Range of tm->tm_year is the years since 1900
|
||||
* But in this RTC, year is split into year and century
|
||||
* In this RTC, century range is [0,31], year range is [0,99]
|
||||
*/
|
||||
int human_year = tm->tm_year + 1900;
|
||||
int rtc_year = human_year % 100;
|
||||
int rtc_century = human_year / 100;
|
||||
|
||||
if (rtc_in_range(rtc_year, 0, 99) &&
|
||||
rtc_in_range(rtc_century, 0, 31))
|
||||
{
|
||||
timer_date.year = rtc_year;
|
||||
timer_extended.century = rtc_century;
|
||||
}
|
||||
else
|
||||
return -1;
|
||||
|
||||
/* Range of tm->tm_wday could be [0, 6] */
|
||||
if (rtc_in_range(tm->tm_wday, 0, 6))
|
||||
timer_date.week = tm->tm_wday;
|
||||
else
|
||||
return -1;
|
||||
|
||||
/* Set RTC mode to timer setting mode */
|
||||
rtc_timer_set_mode(RTC_TIMER_SETTING);
|
||||
/* Write value to RTC */
|
||||
rtc->date = timer_date;
|
||||
rtc->time = timer_time;
|
||||
rtc->extended = timer_extended;
|
||||
/* Get CPU current freq */
|
||||
unsigned long freq = sysctl_clock_get_freq(SYSCTL_CLOCK_CPU);
|
||||
/* Set threshold to 1/26000000 s */
|
||||
freq = freq / 26000000;
|
||||
/* Get current CPU cycle */
|
||||
unsigned long start_cycle = read_cycle();
|
||||
/* Wait for 1/26000000 s to sync data */
|
||||
while (read_cycle() - start_cycle < freq)
|
||||
continue;
|
||||
/* Set RTC mode to timer running mode */
|
||||
rtc_timer_set_mode(RTC_TIMER_RUNNING);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int rtc_timer_set_alarm_tm(const struct tm *tm)
|
||||
{
|
||||
rtc_alarm_date_t alarm_date;
|
||||
rtc_alarm_time_t alarm_time;
|
||||
|
||||
if (tm) {
|
||||
/*
|
||||
* Range of tm->tm_sec could be [0,61]
|
||||
*
|
||||
* Range of tm->tm_sec allows for a positive leap second. Two
|
||||
* leap seconds in the same minute are not allowed (the C90
|
||||
* range 0..61 was a defect)
|
||||
*/
|
||||
if (rtc_in_range(tm->tm_sec, 0, 59))
|
||||
alarm_time.second = tm->tm_sec;
|
||||
else
|
||||
return -1;
|
||||
|
||||
/* Range of tm->tm_min could be [0,59] */
|
||||
if (rtc_in_range(tm->tm_min, 0, 59))
|
||||
alarm_time.minute = tm->tm_min;
|
||||
else
|
||||
return -1;
|
||||
|
||||
/* Range of tm->tm_hour could be [0, 23] */
|
||||
if (rtc_in_range(tm->tm_hour, 0, 23))
|
||||
alarm_time.hour = tm->tm_hour;
|
||||
else
|
||||
return -1;
|
||||
|
||||
/* Range of tm->tm_mday could be [1, 31] */
|
||||
if (rtc_in_range(tm->tm_mday, 1, 31))
|
||||
alarm_date.day = tm->tm_mday;
|
||||
else
|
||||
return -1;
|
||||
|
||||
/*
|
||||
* Range of tm->tm_mon could be [0, 11]
|
||||
* But in this RTC, date.month should be [1, 12]
|
||||
*/
|
||||
if (rtc_in_range(tm->tm_mon, 0, 11))
|
||||
alarm_date.month = tm->tm_mon + 1;
|
||||
else
|
||||
return -1;
|
||||
|
||||
/*
|
||||
* Range of tm->tm_year is the years since 1900
|
||||
* But in this RTC, year is split into year and century
|
||||
* In this RTC, century range is [0,31], year range is [0,99]
|
||||
*/
|
||||
int human_year = tm->tm_year + 1900;
|
||||
int rtc_year = human_year % 100;
|
||||
int rtc_century = human_year / 100;
|
||||
|
||||
if (rtc_in_range(rtc_year, 0, 99) &&
|
||||
rtc_in_range(rtc_century, 0, 31))
|
||||
{
|
||||
alarm_date.year = rtc_year;
|
||||
} else
|
||||
return -1;
|
||||
|
||||
/* Range of tm->tm_wday could be [0, 6] */
|
||||
if (rtc_in_range(tm->tm_wday, 0, 6))
|
||||
alarm_date.week = tm->tm_wday;
|
||||
else
|
||||
return -1;
|
||||
|
||||
/* Write value to RTC */
|
||||
rtc->alarm_date = alarm_date;
|
||||
rtc->alarm_time = alarm_time;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rtc_year_is_leap(int year)
|
||||
{
|
||||
return (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0);
|
||||
}
|
||||
|
||||
static int rtc_get_yday(int year, int month, int day)
|
||||
{
|
||||
static const int days[2][13] =
|
||||
{
|
||||
{0, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334},
|
||||
{0, 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335}
|
||||
};
|
||||
int leap = rtc_year_is_leap(year);
|
||||
|
||||
return days[leap][month] + day;
|
||||
}
|
||||
|
||||
static int rtc_get_wday(int year, int month, int day)
|
||||
{
|
||||
/* Magic method to get weekday */
|
||||
int weekday = (day += month < 3 ? year-- : year - 2, 23 * month / 9 + day + 4 + year / 4 - year / 100 + year / 400) % 7;
|
||||
return weekday;
|
||||
}
|
||||
|
||||
struct tm *rtc_timer_get_tm(void)
|
||||
{
|
||||
if (rtc_timer_get_mode() != RTC_TIMER_RUNNING)
|
||||
return NULL;
|
||||
|
||||
rtc_date_t timer_date = rtc->date;
|
||||
rtc_time_t timer_time = rtc->time;
|
||||
rtc_extended_t timer_extended = rtc->extended;
|
||||
|
||||
struct tm *tm = &rtc_date_time;
|
||||
|
||||
tm->tm_sec = timer_time.second % 60;
|
||||
tm->tm_min = timer_time.minute % 60;
|
||||
tm->tm_hour = timer_time.hour % 24;
|
||||
tm->tm_mday = (timer_date.day - 1) % 31 + 1;
|
||||
tm->tm_mon = (timer_date.month - 1)% 12;
|
||||
tm->tm_year = (timer_date.year % 100) + (timer_extended.century * 100) - 1900;
|
||||
tm->tm_wday = timer_date.week;
|
||||
tm->tm_yday = rtc_get_yday(tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday);
|
||||
tm->tm_isdst = -1;
|
||||
|
||||
return tm;
|
||||
}
|
||||
|
||||
struct tm *rtc_timer_get_alarm_tm(void)
|
||||
{
|
||||
if (rtc_timer_get_mode() != RTC_TIMER_RUNNING)
|
||||
return NULL;
|
||||
|
||||
rtc_alarm_date_t alarm_date = rtc->alarm_date;
|
||||
rtc_alarm_time_t alarm_time = rtc->alarm_time;
|
||||
rtc_extended_t timer_extended = rtc->extended;
|
||||
|
||||
struct tm *tm = &rtc_date_time;
|
||||
|
||||
tm->tm_sec = alarm_time.second % 60;
|
||||
tm->tm_min = alarm_time.minute % 60;
|
||||
tm->tm_hour = alarm_time.hour % 24;
|
||||
tm->tm_mday = alarm_date.day % 31;
|
||||
tm->tm_mon = (alarm_date.month % 12) - 1;
|
||||
/* Alarm and Timer use same timer_extended.century */
|
||||
tm->tm_year = (alarm_date.year % 100) + (timer_extended.century * 100) - 1900;
|
||||
tm->tm_wday = alarm_date.week;
|
||||
tm->tm_yday = rtc_get_yday(tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday);
|
||||
tm->tm_isdst = -1;
|
||||
|
||||
return tm;
|
||||
}
|
||||
|
||||
int rtc_timer_set(int year, int month, int day, int hour, int minute, int second)
|
||||
{
|
||||
struct tm date_time =
|
||||
{
|
||||
.tm_sec = second,
|
||||
.tm_min = minute,
|
||||
.tm_hour = hour,
|
||||
.tm_mday = day,
|
||||
.tm_mon = month - 1,
|
||||
.tm_year = year - 1900,
|
||||
.tm_wday = rtc_get_wday(year, month, day),
|
||||
.tm_yday = rtc_get_yday(year, month, day),
|
||||
.tm_isdst = -1,
|
||||
};
|
||||
return rtc_timer_set_tm(&date_time);
|
||||
}
|
||||
|
||||
int rtc_timer_get(int *year, int *month, int *day, int *hour, int *minute, int *second)
|
||||
{
|
||||
struct tm *tm = rtc_timer_get_tm();
|
||||
|
||||
if (tm)
|
||||
{
|
||||
if (year)
|
||||
*year = tm->tm_year + 1900;
|
||||
if (month)
|
||||
*month = tm->tm_mon + 1;
|
||||
if (day)
|
||||
*day = tm->tm_mday;
|
||||
if (hour)
|
||||
*hour = tm->tm_hour;
|
||||
if (minute)
|
||||
*minute = tm->tm_min;
|
||||
if (second)
|
||||
*second = tm->tm_sec;
|
||||
} else
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int rtc_timer_set_alarm(int year, int month, int day, int hour, int minute, int second)
|
||||
{
|
||||
struct tm date_time = {
|
||||
.tm_sec = second,
|
||||
.tm_min = minute,
|
||||
.tm_hour = hour,
|
||||
.tm_mday = day,
|
||||
.tm_mon = month - 1,
|
||||
.tm_year = year - 1900,
|
||||
.tm_wday = rtc_get_wday(year, month, day),
|
||||
.tm_yday = rtc_get_yday(year, month, day),
|
||||
.tm_isdst = -1,
|
||||
};
|
||||
|
||||
return rtc_timer_set_alarm_tm(&date_time);
|
||||
}
|
||||
|
||||
int rtc_timer_get_alarm(int *year, int *month, int *day, int *hour, int *minute, int *second)
|
||||
{
|
||||
struct tm *tm = rtc_timer_get_alarm_tm();
|
||||
|
||||
if (tm) {
|
||||
if (year)
|
||||
*year = tm->tm_year + 1900;
|
||||
if (month)
|
||||
*month = tm->tm_mon + 1;
|
||||
if (day)
|
||||
*day = tm->tm_mday;
|
||||
if (hour)
|
||||
*hour = tm->tm_hour;
|
||||
if (minute)
|
||||
*minute = tm->tm_min;
|
||||
if (second)
|
||||
*second = tm->tm_sec;
|
||||
} else
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int rtc_timer_set_clock_frequency(unsigned int frequency)
|
||||
{
|
||||
|
||||
rtc_initial_count_t initial_count;
|
||||
|
||||
initial_count.count = frequency;
|
||||
rtc_timer_set_mode(RTC_TIMER_SETTING);
|
||||
rtc->initial_count = initial_count;
|
||||
rtc_timer_set_mode(RTC_TIMER_RUNNING);
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned int rtc_timer_get_clock_frequency(void)
|
||||
{
|
||||
return rtc->initial_count.count;
|
||||
}
|
||||
|
||||
int rtc_timer_set_clock_count_value(unsigned int count)
|
||||
{
|
||||
|
||||
rtc_current_count_t current_count;
|
||||
|
||||
current_count.count = count;
|
||||
rtc_timer_set_mode(RTC_TIMER_SETTING);
|
||||
rtc->current_count = current_count;
|
||||
rtc_timer_set_mode(RTC_TIMER_RUNNING);
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned int rtc_timer_get_clock_count_value(void)
|
||||
{
|
||||
return rtc->current_count.count;
|
||||
}
|
||||
|
||||
int rtc_tick_interrupt_set(int enable)
|
||||
{
|
||||
rtc_interrupt_ctrl_t interrupt_ctrl = rtc->interrupt_ctrl;
|
||||
interrupt_ctrl.tick_enable = enable;
|
||||
rtc_timer_set_mode(RTC_TIMER_SETTING);
|
||||
rtc->interrupt_ctrl = interrupt_ctrl;
|
||||
rtc_timer_set_mode(RTC_TIMER_RUNNING);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int rtc_tick_interrupt_get(void)
|
||||
{
|
||||
rtc_interrupt_ctrl_t interrupt_ctrl = rtc->interrupt_ctrl;
|
||||
|
||||
return interrupt_ctrl.tick_enable;
|
||||
}
|
||||
|
||||
int rtc_tick_interrupt_mode_set(rtc_tick_interrupt_mode_t mode)
|
||||
{
|
||||
rtc_interrupt_ctrl_t interrupt_ctrl = rtc->interrupt_ctrl;
|
||||
|
||||
interrupt_ctrl.tick_int_mode = mode;
|
||||
rtc_timer_set_mode(RTC_TIMER_SETTING);
|
||||
rtc->interrupt_ctrl = interrupt_ctrl;
|
||||
rtc_timer_set_mode(RTC_TIMER_RUNNING);
|
||||
return 0;
|
||||
}
|
||||
|
||||
rtc_tick_interrupt_mode_t rtc_tick_interrupt_mode_get(void)
|
||||
{
|
||||
rtc_interrupt_ctrl_t interrupt_ctrl = rtc->interrupt_ctrl;
|
||||
|
||||
return interrupt_ctrl.tick_int_mode;
|
||||
}
|
||||
|
||||
int rtc_alarm_interrupt_set(int enable)
|
||||
{
|
||||
rtc_interrupt_ctrl_t interrupt_ctrl = rtc->interrupt_ctrl;
|
||||
|
||||
interrupt_ctrl.alarm_enable = enable;
|
||||
rtc->interrupt_ctrl = interrupt_ctrl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int rtc_alarm_interrupt_get(void)
|
||||
{
|
||||
rtc_interrupt_ctrl_t interrupt_ctrl = rtc->interrupt_ctrl;
|
||||
|
||||
return interrupt_ctrl.alarm_enable;
|
||||
}
|
||||
|
||||
int rtc_alarm_interrupt_mask_set(rtc_mask_t mask)
|
||||
{
|
||||
rtc_interrupt_ctrl_t interrupt_ctrl = rtc->interrupt_ctrl;
|
||||
|
||||
interrupt_ctrl.alarm_compare_mask = *(uint8_t *)&mask;
|
||||
rtc->interrupt_ctrl = interrupt_ctrl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
rtc_mask_t rtc_alarm_interrupt_mask_get(void)
|
||||
{
|
||||
rtc_interrupt_ctrl_t interrupt_ctrl = rtc->interrupt_ctrl;
|
||||
|
||||
uint8_t compare_mask = interrupt_ctrl.alarm_compare_mask;
|
||||
|
||||
return *(rtc_mask_t *)&compare_mask;
|
||||
}
|
||||
|
||||
int rtc_protect_set(int enable)
|
||||
{
|
||||
rtc_register_ctrl_t register_ctrl = rtc->register_ctrl;
|
||||
|
||||
rtc_mask_t mask =
|
||||
{
|
||||
.second = 1,
|
||||
/* Second mask */
|
||||
.minute = 1,
|
||||
/* Minute mask */
|
||||
.hour = 1,
|
||||
/* Hour mask */
|
||||
.week = 1,
|
||||
/* Week mask */
|
||||
.day = 1,
|
||||
/* Day mask */
|
||||
.month = 1,
|
||||
/* Month mask */
|
||||
.year = 1,
|
||||
};
|
||||
|
||||
rtc_mask_t unmask =
|
||||
{
|
||||
.second = 0,
|
||||
/* Second mask */
|
||||
.minute = 0,
|
||||
/* Minute mask */
|
||||
.hour = 0,
|
||||
/* Hour mask */
|
||||
.week = 0,
|
||||
/* Week mask */
|
||||
.day = 0,
|
||||
/* Day mask */
|
||||
.month = 0,
|
||||
/* Month mask */
|
||||
.year = 0,
|
||||
};
|
||||
|
||||
if (enable)
|
||||
{
|
||||
/* Turn RTC in protect mode, no one can write time */
|
||||
register_ctrl.timer_mask = *(uint8_t *)&unmask;
|
||||
register_ctrl.alarm_mask = *(uint8_t *)&unmask;
|
||||
register_ctrl.initial_count_mask = 0;
|
||||
register_ctrl.interrupt_register_mask = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Turn RTC in unprotect mode, everyone can write time */
|
||||
register_ctrl.timer_mask = *(uint8_t *)&mask;
|
||||
register_ctrl.alarm_mask = *(uint8_t *)&mask;
|
||||
register_ctrl.initial_count_mask = 1;
|
||||
register_ctrl.interrupt_register_mask = 1;
|
||||
}
|
||||
rtc_timer_set_mode(RTC_TIMER_SETTING);
|
||||
rtc->register_ctrl = register_ctrl;
|
||||
rtc_timer_set_mode(RTC_TIMER_RUNNING);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int rtc_init(void)
|
||||
{
|
||||
/* Reset RTC */
|
||||
sysctl_reset(SYSCTL_RESET_RTC);
|
||||
/* Enable RTC */
|
||||
sysctl_clock_enable(SYSCTL_CLOCK_RTC);
|
||||
/* Unprotect RTC */
|
||||
rtc_protect_set(0);
|
||||
/* Set RTC clock frequency */
|
||||
rtc_timer_set_clock_frequency(
|
||||
sysctl_clock_get_freq(SYSCTL_CLOCK_IN0)
|
||||
);
|
||||
rtc_timer_set_clock_count_value(1);
|
||||
|
||||
/* Set RTC mode to timer running mode */
|
||||
rtc_timer_set_mode(RTC_TIMER_RUNNING);
|
||||
return 0;
|
||||
}
|
||||
@@ -1,120 +0,0 @@
|
||||
/* Copyright 2018 Canaan Inc.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* http://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.
|
||||
*/
|
||||
#include <string.h>
|
||||
#include "sysctl.h"
|
||||
#include "sha256.h"
|
||||
#include "utils.h"
|
||||
|
||||
#define ROTL(x, n) (((x) << (n)) | ((x) >> (32 - (n))))
|
||||
#define ROTR(x, n) (((x) >> (n)) | ((x) << (32 - (n))))
|
||||
#define BYTESWAP(x) ((ROTR((x), 8) & 0xff00ff00L) | (ROTL((x), 8) & 0x00ff00ffL))
|
||||
#define BYTESWAP64(x) byteswap64(x)
|
||||
|
||||
volatile sha256_t* const sha256 = (volatile sha256_t*)SHA256_BASE_ADDR;
|
||||
static const uint8_t padding[64] =
|
||||
{
|
||||
0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
};
|
||||
|
||||
static inline uint64_t byteswap64(uint64_t x)
|
||||
{
|
||||
uint32_t a = (uint32_t)(x >> 32);
|
||||
uint32_t b = (uint32_t)x;
|
||||
return ((uint64_t)BYTESWAP(b) << 32) | (uint64_t)BYTESWAP(a);
|
||||
}
|
||||
|
||||
void sha256_init(sha256_context_t *context, size_t input_len)
|
||||
{
|
||||
sysctl_clock_enable(SYSCTL_CLOCK_SHA);
|
||||
sysctl_reset(SYSCTL_RESET_SHA);
|
||||
|
||||
sha256->sha_num_reg.sha_data_cnt = (uint32_t)((input_len + SHA256_BLOCK_LEN + 8) / SHA256_BLOCK_LEN);
|
||||
sha256->sha_function_reg_1.dma_en = 0x0;
|
||||
sha256->sha_function_reg_0.sha_endian = SHA256_BIG_ENDIAN;
|
||||
sha256->sha_function_reg_0.sha_en = ENABLE_SHA;
|
||||
context->total_len = 0L;
|
||||
context->buffer_len = 0L;
|
||||
}
|
||||
|
||||
void sha256_update(sha256_context_t *context, const void *input, size_t input_len)
|
||||
{
|
||||
const uint8_t *data = input;
|
||||
size_t buffer_bytes_left;
|
||||
size_t bytes_to_copy;
|
||||
uint32_t i;
|
||||
|
||||
while (input_len)
|
||||
{
|
||||
buffer_bytes_left = SHA256_BLOCK_LEN - context->buffer_len;
|
||||
bytes_to_copy = buffer_bytes_left;
|
||||
if (bytes_to_copy > input_len)
|
||||
bytes_to_copy = input_len;
|
||||
memcpy(&context->buffer.bytes[context->buffer_len], data, bytes_to_copy);
|
||||
context->total_len += bytes_to_copy * 8L;
|
||||
context->buffer_len += bytes_to_copy;
|
||||
data += bytes_to_copy;
|
||||
input_len -= bytes_to_copy;
|
||||
if (context->buffer_len == SHA256_BLOCK_LEN)
|
||||
{
|
||||
for (i = 0; i < 16; i++)
|
||||
{
|
||||
while (sha256->sha_function_reg_1.fifo_in_full)
|
||||
;
|
||||
sha256->sha_data_in1 = context->buffer.words[i];
|
||||
}
|
||||
context->buffer_len = 0L;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void sha256_final(sha256_context_t *context, uint8_t *output)
|
||||
{
|
||||
size_t bytes_to_pad;
|
||||
size_t length_pad;
|
||||
uint32_t i;
|
||||
|
||||
bytes_to_pad = 120L - context->buffer_len;
|
||||
if (bytes_to_pad > 64L)
|
||||
bytes_to_pad -= 64L;
|
||||
length_pad = BYTESWAP64(context->total_len);
|
||||
sha256_update(context, padding, bytes_to_pad);
|
||||
sha256_update(context, &length_pad, 8L);
|
||||
while (!(sha256->sha_function_reg_0.sha_en))
|
||||
;
|
||||
if (output)
|
||||
{
|
||||
for (i = 0; i < SHA256_HASH_WORDS; i++)
|
||||
{
|
||||
*((uint32_t *)output) = sha256->sha_result[SHA256_HASH_WORDS - i - 1];
|
||||
output += 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void sha256_hard_calculate(const uint8_t *input, size_t input_len, uint8_t *output)
|
||||
{
|
||||
sha256_context_t sha;
|
||||
sha256_init(&sha, input_len);
|
||||
sha256_update(&sha, input, input_len);
|
||||
sha256_final(&sha, output);
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,391 +0,0 @@
|
||||
/* Copyright 2018 Canaan Inc.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* http://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.
|
||||
*/
|
||||
|
||||
#include <syslog.h>
|
||||
#include "timer.h"
|
||||
#include "sysctl.h"
|
||||
#include "stddef.h"
|
||||
#include "utils.h"
|
||||
#include "plic.h"
|
||||
#include "io.h"
|
||||
|
||||
/**
|
||||
* @brief Private definitions for the timer instance
|
||||
*/
|
||||
typedef struct timer_instance
|
||||
{
|
||||
timer_callback_t callback;
|
||||
void *ctx;
|
||||
bool single_shot;
|
||||
} timer_instance_t;
|
||||
|
||||
volatile timer_instance_t timer_instance[TIMER_DEVICE_MAX][TIMER_CHANNEL_MAX];
|
||||
|
||||
volatile kendryte_timer_t *const timer[3] =
|
||||
{
|
||||
(volatile kendryte_timer_t *)TIMER0_BASE_ADDR,
|
||||
(volatile kendryte_timer_t *)TIMER1_BASE_ADDR,
|
||||
(volatile kendryte_timer_t *)TIMER2_BASE_ADDR
|
||||
};
|
||||
|
||||
void timer_init(timer_device_number_t timer_number)
|
||||
{
|
||||
for(size_t i = 0; i < TIMER_CHANNEL_MAX; i++)
|
||||
timer_instance[timer_number][i] = (const timer_instance_t) {
|
||||
.callback = NULL,
|
||||
.ctx = NULL,
|
||||
.single_shot = 0,
|
||||
};
|
||||
|
||||
sysctl_clock_enable(SYSCTL_CLOCK_TIMER0 + timer_number);
|
||||
}
|
||||
|
||||
void timer_set_clock_div(timer_device_number_t timer_number, uint32_t div)
|
||||
{
|
||||
sysctl_clock_set_threshold(timer_number == 0 ? SYSCTL_THRESHOLD_TIMER0 :
|
||||
timer_number == 1 ? SYSCTL_THRESHOLD_TIMER1 :
|
||||
SYSCTL_THRESHOLD_TIMER2, div);
|
||||
}
|
||||
|
||||
void timer_enable(timer_device_number_t timer_number, timer_channel_number_t channel)
|
||||
{
|
||||
timer[timer_number]->channel[channel].control |= TIMER_CR_ENABLE;
|
||||
}
|
||||
|
||||
void timer_disable(timer_device_number_t timer_number, timer_channel_number_t channel)
|
||||
{
|
||||
timer[timer_number]->channel[channel].control &= (~TIMER_CR_ENABLE);
|
||||
}
|
||||
|
||||
void timer_enable_pwm(timer_device_number_t timer_number, timer_channel_number_t channel)
|
||||
{
|
||||
timer[timer_number]->channel[channel].control |= TIMER_CR_PWM_ENABLE;
|
||||
}
|
||||
|
||||
void timer_disable_pwm(timer_device_number_t timer_number, timer_channel_number_t channel)
|
||||
{
|
||||
timer[timer_number]->channel[channel].control &= (~TIMER_CR_PWM_ENABLE);
|
||||
}
|
||||
|
||||
void timer_enable_interrupt(timer_device_number_t timer_number, timer_channel_number_t channel)
|
||||
{
|
||||
timer[timer_number]->channel[channel].control &= (~TIMER_CR_INTERRUPT_MASK);
|
||||
}
|
||||
|
||||
void timer_disable_interrupt(timer_device_number_t timer_number, timer_channel_number_t channel)
|
||||
{
|
||||
timer[timer_number]->channel[channel].control |= TIMER_CR_INTERRUPT_MASK;
|
||||
}
|
||||
|
||||
void timer_set_mode(timer_device_number_t timer_number, timer_channel_number_t channel, uint32_t mode)
|
||||
{
|
||||
timer[timer_number]->channel[channel].control &= (~TIMER_CR_MODE_MASK);
|
||||
timer[timer_number]->channel[channel].control |= mode;
|
||||
}
|
||||
|
||||
void timer_set_reload(timer_device_number_t timer_number, timer_channel_number_t channel, uint32_t count)
|
||||
{
|
||||
timer[timer_number]->channel[channel].load_count = count;
|
||||
}
|
||||
|
||||
void timer_set_reload2(timer_device_number_t timer_number, timer_channel_number_t channel, uint32_t count)
|
||||
{
|
||||
timer[timer_number]->load_count2[channel] = count;
|
||||
}
|
||||
|
||||
uint32_t timer_get_count(timer_device_number_t timer_number, timer_channel_number_t channel)
|
||||
{
|
||||
return timer[timer_number]->channel[channel].current_value;
|
||||
}
|
||||
|
||||
uint32_t timer_get_reload(timer_device_number_t timer_number, timer_channel_number_t channel)
|
||||
{
|
||||
return timer[timer_number]->channel[channel].load_count;
|
||||
}
|
||||
|
||||
uint32_t timer_get_reload2(timer_device_number_t timer_number, timer_channel_number_t channel)
|
||||
{
|
||||
return timer[timer_number]->load_count2[channel];
|
||||
}
|
||||
|
||||
uint32_t timer_get_interrupt_status(timer_device_number_t timer_number)
|
||||
{
|
||||
return timer[timer_number]->intr_stat;
|
||||
}
|
||||
|
||||
uint32_t timer_get_raw_interrupt_status(timer_device_number_t timer_number)
|
||||
{
|
||||
return timer[timer_number]->raw_intr_stat;
|
||||
}
|
||||
|
||||
uint32_t timer_channel_get_interrupt_status(timer_device_number_t timer_number, timer_channel_number_t channel)
|
||||
{
|
||||
return timer[timer_number]->channel[channel].intr_stat;
|
||||
}
|
||||
|
||||
void timer_clear_interrupt(timer_device_number_t timer_number)
|
||||
{
|
||||
timer[timer_number]->eoi = timer[timer_number]->eoi;
|
||||
}
|
||||
|
||||
void timer_channel_clear_interrupt(timer_device_number_t timer_number, timer_channel_number_t channel)
|
||||
{
|
||||
timer[timer_number]->channel[channel].eoi = timer[timer_number]->channel[channel].eoi;
|
||||
}
|
||||
|
||||
void timer_set_enable(timer_device_number_t timer_number, timer_channel_number_t channel, uint32_t enable)
|
||||
{
|
||||
if (enable)
|
||||
timer[timer_number]->channel[channel].control = TIMER_CR_USER_MODE | TIMER_CR_ENABLE;
|
||||
else
|
||||
timer[timer_number]->channel[channel].control = TIMER_CR_INTERRUPT_MASK;
|
||||
}
|
||||
|
||||
size_t timer_set_interval(timer_device_number_t timer_number, timer_channel_number_t channel, size_t nanoseconds)
|
||||
{
|
||||
uint32_t clk_freq = sysctl_clock_get_freq(SYSCTL_CLOCK_TIMER0 + timer_number);
|
||||
|
||||
double min_step = 1e9 / clk_freq;
|
||||
size_t value = (size_t)(nanoseconds / min_step);
|
||||
configASSERT(value > 0 && value < UINT32_MAX);
|
||||
timer[timer_number]->channel[channel].load_count = (uint32_t)value;
|
||||
return (size_t)(min_step * value);
|
||||
}
|
||||
|
||||
typedef void(*timer_ontick)();
|
||||
timer_ontick time_irq[3][4] = { NULL };
|
||||
|
||||
static int timer_isr(void *parm)
|
||||
{
|
||||
uint32_t timer_number;
|
||||
for (timer_number = 0; timer_number < 3; timer_number++)
|
||||
{
|
||||
if (parm == timer[timer_number])
|
||||
break;
|
||||
}
|
||||
|
||||
uint32_t channel = timer[timer_number]->intr_stat;
|
||||
size_t i = 0;
|
||||
for (i = 0; i < 4; i++)
|
||||
{
|
||||
if (channel & 1)
|
||||
{
|
||||
if (time_irq[timer_number][i])
|
||||
(time_irq[timer_number][i])();
|
||||
break;
|
||||
}
|
||||
|
||||
channel >>= 1;
|
||||
}
|
||||
|
||||
readl(&timer[timer_number]->eoi);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void timer_set_irq(timer_device_number_t timer_number, timer_channel_number_t channel, void(*func)(), uint32_t priority)
|
||||
{
|
||||
time_irq[timer_number][channel] = func;
|
||||
if (channel < 2)
|
||||
{
|
||||
plic_set_priority(IRQN_TIMER0A_INTERRUPT + timer_number * 2, priority);
|
||||
plic_irq_register(IRQN_TIMER0A_INTERRUPT + timer_number * 2, timer_isr, (void *)timer[timer_number]);
|
||||
plic_irq_enable(IRQN_TIMER0A_INTERRUPT + timer_number * 2);
|
||||
}
|
||||
else
|
||||
{
|
||||
plic_set_priority(IRQN_TIMER0B_INTERRUPT + timer_number * 2, priority);
|
||||
plic_irq_register(IRQN_TIMER0B_INTERRUPT + timer_number * 2, timer_isr, (void *)timer[timer_number]);
|
||||
plic_irq_enable(IRQN_TIMER0B_INTERRUPT + timer_number * 2);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the timer irqn by device and channel object
|
||||
*
|
||||
* @note Internal function, not public
|
||||
* @param device The device
|
||||
* @param channel The channel
|
||||
* @return plic_irq_t IRQ number
|
||||
*/
|
||||
static plic_irq_t get_timer_irqn_by_device_and_channel(timer_device_number_t device, timer_channel_number_t channel)
|
||||
{
|
||||
if (device < TIMER_DEVICE_MAX && channel < TIMER_CHANNEL_MAX) {
|
||||
/*
|
||||
* Select timer interrupt part
|
||||
* Hierarchy of Timer interrupt to PLIC
|
||||
* +---------+ +-----------+
|
||||
* | 0+----+ | |
|
||||
* | | +--+0A |
|
||||
* | 1+----+ | |
|
||||
* | TIMER0 | | |
|
||||
* | 2+----+ | |
|
||||
* | | +--+0B |
|
||||
* | 3+----+ | |
|
||||
* +---------+ | |
|
||||
* | |
|
||||
* +---------+ | |
|
||||
* | 0+----+ | |
|
||||
* | | +--+1A |
|
||||
* | 1+----+ | |
|
||||
* | TIMER1 | | PLIC |
|
||||
* | 2+----+ | |
|
||||
* | | +--+1B |
|
||||
* | 3+----+ | |
|
||||
* +---------+ | |
|
||||
* | |
|
||||
* +---------+ | |
|
||||
* | 0+----+ | |
|
||||
* | | +--+2A |
|
||||
* | 1+----+ | |
|
||||
* | TIMER2 | | |
|
||||
* | 2+----+ | |
|
||||
* | | +--+2B |
|
||||
* | 3+----+ | |
|
||||
* +---------+ +-----------+
|
||||
*
|
||||
*/
|
||||
if (channel < 2) {
|
||||
/* It is part A interrupt, offset + 0 */
|
||||
return IRQN_TIMER0A_INTERRUPT + device * 2;
|
||||
}
|
||||
else {
|
||||
/* It is part B interrupt, offset + 1 */
|
||||
return IRQN_TIMER0B_INTERRUPT + device * 2;
|
||||
}
|
||||
}
|
||||
return IRQN_NO_INTERRUPT;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Process user callback function
|
||||
*
|
||||
* @note Internal function, not public
|
||||
* @param device The timer device
|
||||
* @param ctx The context
|
||||
* @return int The callback result
|
||||
*/
|
||||
static int timer_interrupt_handler(timer_device_number_t device, void *ctx)
|
||||
{
|
||||
uint32_t channel_int_stat = timer[device]->intr_stat;
|
||||
|
||||
for (size_t i = 0; i < TIMER_CHANNEL_MAX; i++)
|
||||
{
|
||||
/* Check every bit for interrupt status */
|
||||
if (channel_int_stat & 1)
|
||||
{
|
||||
if (timer_instance[device][i].callback) {
|
||||
/* Process user callback function */
|
||||
timer_instance[device][i].callback(timer_instance[device][i].ctx);
|
||||
/* Check if this timer is a single shot timer */
|
||||
if (timer_instance[device][i].single_shot) {
|
||||
/* Single shot timer, disable it */
|
||||
timer_set_enable(device, i, 0);
|
||||
}
|
||||
}
|
||||
/* Clear timer interrupt flag for specific channel */
|
||||
readl(&timer[device]->channel[i].eoi);
|
||||
}
|
||||
channel_int_stat >>= 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* NOTE:
|
||||
* Don't read timer[device]->eoi here, or you will lost some interrupt
|
||||
* readl(&timer[device]->eoi);
|
||||
*/
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Callback function bus for timer interrupt
|
||||
*
|
||||
* @note Internal function, not public
|
||||
* @param ctx The context
|
||||
* @return int The callback result
|
||||
*/
|
||||
static int timer0_interrupt_callback(void *ctx)
|
||||
{
|
||||
return timer_interrupt_handler(TIMER_DEVICE_0, ctx);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Callback function bus for timer interrupt
|
||||
*
|
||||
* @note Internal function, not public
|
||||
* @param ctx The context
|
||||
* @return int The callback result
|
||||
*/
|
||||
static int timer1_interrupt_callback(void *ctx)
|
||||
{
|
||||
return timer_interrupt_handler(TIMER_DEVICE_1, ctx);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Callback function bus for timer interrupt
|
||||
*
|
||||
* @note Internal function, not public
|
||||
* @param ctx The context
|
||||
* @return int The callback result
|
||||
*/
|
||||
static int timer2_interrupt_callback(void *ctx)
|
||||
{
|
||||
return timer_interrupt_handler(TIMER_DEVICE_2, ctx);
|
||||
}
|
||||
|
||||
int timer_irq_register(timer_device_number_t device, timer_channel_number_t channel, int is_single_shot, uint32_t priority, timer_callback_t callback, void *ctx)
|
||||
{
|
||||
if (device < TIMER_DEVICE_MAX && channel < TIMER_CHANNEL_MAX) {
|
||||
plic_irq_t irq_number = get_timer_irqn_by_device_and_channel(device, channel);
|
||||
plic_irq_callback_t plic_irq_callback[TIMER_DEVICE_MAX] = {
|
||||
timer0_interrupt_callback,
|
||||
timer1_interrupt_callback,
|
||||
timer2_interrupt_callback,
|
||||
};
|
||||
|
||||
timer_instance[device][channel] = (const timer_instance_t) {
|
||||
.callback = callback,
|
||||
.ctx = ctx,
|
||||
.single_shot = is_single_shot,
|
||||
};
|
||||
plic_set_priority(irq_number, priority);
|
||||
plic_irq_register(irq_number, plic_irq_callback[device], (void *)&timer_instance[device]);
|
||||
plic_irq_enable(irq_number);
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int timer_irq_unregister(timer_device_number_t device, timer_channel_number_t channel)
|
||||
{
|
||||
if (device < TIMER_DEVICE_MAX && channel < TIMER_CHANNEL_MAX) {
|
||||
timer_instance[device][channel] = (const timer_instance_t) {
|
||||
.callback = NULL,
|
||||
.ctx = NULL,
|
||||
.single_shot = 0,
|
||||
};
|
||||
|
||||
/* Combine 0 and 1 to A interrupt, 2 and 3 to B interrupt */
|
||||
if ((!(timer_instance[device][TIMER_CHANNEL_0].callback ||
|
||||
timer_instance[device][TIMER_CHANNEL_1].callback)) ||
|
||||
(!(timer_instance[device][TIMER_CHANNEL_2].callback ||
|
||||
timer_instance[device][TIMER_CHANNEL_3].callback))) {
|
||||
plic_irq_t irq_number = get_timer_irqn_by_device_and_channel(device, channel);
|
||||
plic_irq_unregister(irq_number);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
@@ -1,338 +0,0 @@
|
||||
/* Copyright 2018 Canaan Inc.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* http://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.
|
||||
*/
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include "plic.h"
|
||||
#include "sysctl.h"
|
||||
#include "uart.h"
|
||||
#include "utils.h"
|
||||
#include "atomic.h"
|
||||
|
||||
#define __UART_BRATE_CONST 16
|
||||
|
||||
volatile uart_t* const uart[3] =
|
||||
{
|
||||
(volatile uart_t*)UART1_BASE_ADDR,
|
||||
(volatile uart_t*)UART2_BASE_ADDR,
|
||||
(volatile uart_t*)UART3_BASE_ADDR
|
||||
};
|
||||
|
||||
#define UART_INTERRUPT_SEND 0x02U
|
||||
#define UART_INTERRUPT_RECEIVE 0x04U
|
||||
#define UART_INTERRUPT_CHARACTER_TIMEOUT 0x0CU
|
||||
|
||||
typedef struct _uart_interrupt_instance
|
||||
{
|
||||
plic_irq_callback_t callback;
|
||||
void *ctx;
|
||||
} uart_interrupt_instance_t;
|
||||
|
||||
typedef struct _uart_instance
|
||||
{
|
||||
uart_interrupt_instance_t uart_receive_instance;
|
||||
uart_interrupt_instance_t uart_send_instance;
|
||||
uint32_t uart_num;
|
||||
} uart_instance_t;
|
||||
|
||||
uart_instance_t g_uart_instance[3];
|
||||
|
||||
typedef struct _uart_dma_instance
|
||||
{
|
||||
uint8_t *buffer;
|
||||
size_t buf_len;
|
||||
uint32_t *malloc_buffer;
|
||||
uart_interrupt_mode_t int_mode;
|
||||
dmac_channel_number_t dmac_channel;
|
||||
uart_device_number_t uart_num;
|
||||
uart_interrupt_instance_t uart_int_instance;
|
||||
} uart_dma_instance_t;
|
||||
|
||||
uart_dma_instance_t uart_send_dma_instance[3];
|
||||
uart_dma_instance_t uart_recv_dma_instance[3];
|
||||
|
||||
volatile int g_write_count = 0;
|
||||
|
||||
static int uart_irq_callback(void *param)
|
||||
{
|
||||
uart_instance_t *uart_instance = (uart_instance_t *)param;
|
||||
uint32_t v_channel = uart_instance->uart_num;
|
||||
uint8_t v_int_status = uart[v_channel]->IIR & 0xF;
|
||||
|
||||
if(v_int_status == UART_INTERRUPT_SEND && g_write_count != 0)
|
||||
{
|
||||
if(uart_instance->uart_send_instance.callback != NULL)
|
||||
uart_instance->uart_send_instance.callback(uart_instance->uart_send_instance.ctx);
|
||||
}
|
||||
else if(v_int_status == UART_INTERRUPT_RECEIVE || v_int_status == UART_INTERRUPT_CHARACTER_TIMEOUT)
|
||||
{
|
||||
if(uart_instance->uart_receive_instance.callback != NULL)
|
||||
uart_instance->uart_receive_instance.callback(uart_instance->uart_receive_instance.ctx);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int uartapb_putc(uart_device_number_t channel, char c)
|
||||
{
|
||||
while (uart[channel]->LSR & (1u << 5))
|
||||
continue;
|
||||
uart[channel]->THR = c;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uartapb_getc(uart_device_number_t channel)
|
||||
{
|
||||
while (!(uart[channel]->LSR & 1))
|
||||
continue;
|
||||
|
||||
return (char)(uart[channel]->RBR & 0xff);
|
||||
}
|
||||
|
||||
static int uart_dma_callback(void *ctx)
|
||||
{
|
||||
uart_dma_instance_t *v_uart_dma_instance = (uart_dma_instance_t *)ctx;
|
||||
dmac_channel_number_t dmac_channel = v_uart_dma_instance->dmac_channel;
|
||||
dmac_irq_unregister(dmac_channel);
|
||||
|
||||
if(v_uart_dma_instance->int_mode == UART_RECEIVE)
|
||||
{
|
||||
size_t v_buf_len = v_uart_dma_instance->buf_len;
|
||||
uint8_t *v_buffer = v_uart_dma_instance->buffer;
|
||||
uint32_t *v_recv_buffer = v_uart_dma_instance->malloc_buffer;
|
||||
for(size_t i = 0; i < v_buf_len; i++)
|
||||
{
|
||||
v_buffer[i] = v_recv_buffer[i];
|
||||
}
|
||||
}
|
||||
free(v_uart_dma_instance->malloc_buffer);
|
||||
if(v_uart_dma_instance->uart_int_instance.callback)
|
||||
v_uart_dma_instance->uart_int_instance.callback(v_uart_dma_instance->uart_int_instance.ctx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uart_receive_data(uart_device_number_t channel, char *buffer, size_t buf_len)
|
||||
{
|
||||
size_t i = 0;
|
||||
for(i = 0;i < buf_len; i++)
|
||||
{
|
||||
if(uart[channel]->LSR & 1)
|
||||
buffer[i] = (char)(uart[channel]->RBR & 0xff);
|
||||
else
|
||||
break;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
void uart_receive_data_dma(uart_device_number_t uart_channel, dmac_channel_number_t dmac_channel, uint8_t *buffer, size_t buf_len)
|
||||
{
|
||||
uint32_t *v_recv_buf = malloc(buf_len * sizeof(uint32_t));
|
||||
configASSERT(v_recv_buf!=NULL);
|
||||
|
||||
sysctl_dma_select((sysctl_dma_channel_t)dmac_channel, SYSCTL_DMA_SELECT_UART1_RX_REQ + uart_channel * 2);
|
||||
dmac_set_single_mode(dmac_channel, (void *)(&uart[uart_channel]->RBR), v_recv_buf, DMAC_ADDR_NOCHANGE, DMAC_ADDR_INCREMENT,
|
||||
DMAC_MSIZE_1, DMAC_TRANS_WIDTH_32, buf_len);
|
||||
dmac_wait_done(dmac_channel);
|
||||
for(uint32_t i = 0; i < buf_len; i++)
|
||||
{
|
||||
buffer[i] = (uint8_t)(v_recv_buf[i] & 0xff);
|
||||
}
|
||||
}
|
||||
|
||||
void uart_receive_data_dma_irq(uart_device_number_t uart_channel, dmac_channel_number_t dmac_channel,
|
||||
uint8_t *buffer, size_t buf_len, plic_irq_callback_t uart_callback,
|
||||
void *ctx, uint32_t priority)
|
||||
{
|
||||
uint32_t *v_recv_buf = malloc(buf_len * sizeof(uint32_t));
|
||||
configASSERT(v_recv_buf!=NULL);
|
||||
|
||||
uart_recv_dma_instance[uart_channel].dmac_channel = dmac_channel;
|
||||
uart_recv_dma_instance[uart_channel].uart_num = uart_channel;
|
||||
uart_recv_dma_instance[uart_channel].malloc_buffer = v_recv_buf;
|
||||
uart_recv_dma_instance[uart_channel].buffer = buffer;
|
||||
uart_recv_dma_instance[uart_channel].buf_len = buf_len;
|
||||
uart_recv_dma_instance[uart_channel].int_mode = UART_RECEIVE;
|
||||
uart_recv_dma_instance[uart_channel].uart_int_instance.callback = uart_callback;
|
||||
uart_recv_dma_instance[uart_channel].uart_int_instance.ctx = ctx;
|
||||
|
||||
dmac_irq_register(dmac_channel, uart_dma_callback, &uart_recv_dma_instance[uart_channel], priority);
|
||||
sysctl_dma_select((sysctl_dma_channel_t)dmac_channel, SYSCTL_DMA_SELECT_UART1_RX_REQ + uart_channel * 2);
|
||||
dmac_set_single_mode(dmac_channel, (void *)(&uart[uart_channel]->RBR), v_recv_buf, DMAC_ADDR_NOCHANGE, DMAC_ADDR_INCREMENT,
|
||||
DMAC_MSIZE_1, DMAC_TRANS_WIDTH_32, buf_len);
|
||||
}
|
||||
|
||||
int uart_send_data(uart_device_number_t channel, const char *buffer, size_t buf_len)
|
||||
{
|
||||
g_write_count = 0;
|
||||
while (g_write_count < buf_len)
|
||||
{
|
||||
uartapb_putc(channel, *buffer++);
|
||||
g_write_count++;
|
||||
}
|
||||
return g_write_count;
|
||||
}
|
||||
|
||||
void uart_send_data_dma(uart_device_number_t uart_channel, dmac_channel_number_t dmac_channel, const uint8_t *buffer, size_t buf_len)
|
||||
{
|
||||
uint32_t *v_send_buf = malloc(buf_len * sizeof(uint32_t));
|
||||
configASSERT(v_send_buf!=NULL);
|
||||
for(uint32_t i = 0; i < buf_len; i++)
|
||||
v_send_buf[i] = buffer[i];
|
||||
sysctl_dma_select((sysctl_dma_channel_t)dmac_channel, SYSCTL_DMA_SELECT_UART1_TX_REQ + uart_channel * 2);
|
||||
dmac_set_single_mode(dmac_channel, v_send_buf, (void *)(&uart[uart_channel]->THR), DMAC_ADDR_INCREMENT, DMAC_ADDR_NOCHANGE,
|
||||
DMAC_MSIZE_1, DMAC_TRANS_WIDTH_32, buf_len);
|
||||
dmac_wait_done(dmac_channel);
|
||||
free((void *)v_send_buf);
|
||||
}
|
||||
|
||||
void uart_send_data_dma_irq(uart_device_number_t uart_channel, dmac_channel_number_t dmac_channel,
|
||||
const uint8_t *buffer, size_t buf_len, plic_irq_callback_t uart_callback,
|
||||
void *ctx, uint32_t priority)
|
||||
{
|
||||
uint32_t *v_send_buf = malloc(buf_len * sizeof(uint32_t));
|
||||
configASSERT(v_send_buf!=NULL);
|
||||
|
||||
uart_send_dma_instance[uart_channel] = (uart_dma_instance_t) {
|
||||
.dmac_channel = dmac_channel,
|
||||
.uart_num = uart_channel,
|
||||
.malloc_buffer = v_send_buf,
|
||||
.buffer = (uint8_t *)buffer,
|
||||
.buf_len = buf_len,
|
||||
.int_mode = UART_SEND,
|
||||
.uart_int_instance.callback = uart_callback,
|
||||
.uart_int_instance.ctx = ctx,
|
||||
};
|
||||
|
||||
for(uint32_t i = 0; i < buf_len; i++)
|
||||
v_send_buf[i] = buffer[i];
|
||||
dmac_irq_register(dmac_channel, uart_dma_callback, &uart_send_dma_instance[uart_channel], priority);
|
||||
sysctl_dma_select((sysctl_dma_channel_t)dmac_channel, SYSCTL_DMA_SELECT_UART1_TX_REQ + uart_channel * 2);
|
||||
dmac_set_single_mode(dmac_channel, v_send_buf, (void *)(&uart[uart_channel]->THR), DMAC_ADDR_INCREMENT, DMAC_ADDR_NOCHANGE,
|
||||
DMAC_MSIZE_1, DMAC_TRANS_WIDTH_32, buf_len);
|
||||
|
||||
}
|
||||
|
||||
void uart_configure(uart_device_number_t channel, uint32_t baud_rate, uart_bitwidth_t data_width, uart_stopbit_t stopbit, uart_parity_t parity)
|
||||
{
|
||||
configASSERT(data_width >= 5 && data_width <= 8);
|
||||
if (data_width == 5)
|
||||
{
|
||||
configASSERT(stopbit != UART_STOP_2);
|
||||
}
|
||||
else
|
||||
{
|
||||
configASSERT(stopbit != UART_STOP_1_5);
|
||||
}
|
||||
|
||||
uint32_t stopbit_val = stopbit == UART_STOP_1 ? 0 : 1;
|
||||
uint32_t parity_val;
|
||||
switch (parity)
|
||||
{
|
||||
case UART_PARITY_NONE:
|
||||
parity_val = 0;
|
||||
break;
|
||||
case UART_PARITY_ODD:
|
||||
parity_val = 1;
|
||||
break;
|
||||
case UART_PARITY_EVEN:
|
||||
parity_val = 3;
|
||||
break;
|
||||
default:
|
||||
configASSERT(!"Invalid parity");
|
||||
break;
|
||||
}
|
||||
|
||||
uint32_t freq = sysctl_clock_get_freq(SYSCTL_CLOCK_APB0);
|
||||
uint32_t divisor = freq / baud_rate;
|
||||
uint8_t dlh = divisor >> 12;
|
||||
uint8_t dll = (divisor - (dlh << 12)) / __UART_BRATE_CONST;
|
||||
uint8_t dlf = divisor - (dlh << 12) - dll * __UART_BRATE_CONST;
|
||||
|
||||
/* Set UART registers */
|
||||
uart[channel]->TCR &= ~(1u);
|
||||
uart[channel]->TCR &= ~(1u << 3);
|
||||
uart[channel]->TCR &= ~(1u << 4);
|
||||
uart[channel]->TCR |= (1u << 2);
|
||||
uart[channel]->TCR &= ~(1u << 1);
|
||||
uart[channel]->DE_EN &= ~(1u);
|
||||
|
||||
uart[channel]->LCR |= 1u << 7;
|
||||
uart[channel]->DLH = dlh;
|
||||
uart[channel]->DLL = dll;
|
||||
uart[channel]->DLF = dlf;
|
||||
uart[channel]->LCR = 0;
|
||||
uart[channel]->LCR = (data_width - 5) | (stopbit_val << 2) | (parity_val << 3);
|
||||
uart[channel]->LCR &= ~(1u << 7);
|
||||
uart[channel]->MCR &= ~3;
|
||||
uart[channel]->IER |= 0x80; /* THRE */
|
||||
uart[channel]->FCR = UART_RECEIVE_FIFO_1 << 6 | UART_SEND_FIFO_8 << 4 | 0x1 << 3 | 0x1;
|
||||
}
|
||||
|
||||
void __attribute__((weak, alias("uart_configure")))
|
||||
uart_config(uart_device_number_t channel, uint32_t baud_rate, uart_bitwidth_t data_width, uart_stopbit_t stopbit, uart_parity_t parity);
|
||||
|
||||
void uart_init(uart_device_number_t channel)
|
||||
{
|
||||
sysctl_clock_enable(SYSCTL_CLOCK_UART1 + channel);
|
||||
}
|
||||
|
||||
void uart_set_send_trigger(uart_device_number_t channel, uart_send_trigger_t trigger)
|
||||
{
|
||||
uart[channel]->STET = trigger;
|
||||
}
|
||||
|
||||
void uart_set_receive_trigger(uart_device_number_t channel, uart_receive_trigger_t trigger)
|
||||
{
|
||||
uart[channel]->SRT = trigger;
|
||||
}
|
||||
|
||||
void uart_irq_register(uart_device_number_t channel, uart_interrupt_mode_t interrupt_mode, plic_irq_callback_t uart_callback, void *ctx, uint32_t priority)
|
||||
{
|
||||
if(interrupt_mode == UART_SEND)
|
||||
{
|
||||
uart[channel]->IER |= 0x2;
|
||||
g_uart_instance[channel].uart_send_instance.callback = uart_callback;
|
||||
g_uart_instance[channel].uart_send_instance.ctx = ctx;
|
||||
}
|
||||
else if(interrupt_mode == UART_RECEIVE)
|
||||
{
|
||||
uart[channel]->IER |= 0x1;
|
||||
g_uart_instance[channel].uart_receive_instance.callback = uart_callback;
|
||||
g_uart_instance[channel].uart_receive_instance.ctx = ctx;
|
||||
}
|
||||
g_uart_instance[channel].uart_num = channel;
|
||||
plic_set_priority(IRQN_UART1_INTERRUPT + channel, priority);
|
||||
plic_irq_register(IRQN_UART1_INTERRUPT + channel, uart_irq_callback, &g_uart_instance[channel]);
|
||||
plic_irq_enable(IRQN_UART1_INTERRUPT + channel);
|
||||
}
|
||||
|
||||
void uart_irq_unregister(uart_device_number_t channel, uart_interrupt_mode_t interrupt_mode)
|
||||
{
|
||||
if(interrupt_mode == UART_SEND)
|
||||
{
|
||||
uart[channel]->IER &= ~(0x2);
|
||||
g_uart_instance[channel].uart_send_instance.callback = NULL;
|
||||
g_uart_instance[channel].uart_send_instance.ctx = NULL;
|
||||
}
|
||||
else if(interrupt_mode == UART_RECEIVE)
|
||||
{
|
||||
uart[channel]->IER &= ~(0x1);
|
||||
g_uart_instance[channel].uart_receive_instance.callback = NULL;
|
||||
g_uart_instance[channel].uart_receive_instance.ctx = NULL;
|
||||
}
|
||||
if(uart[channel]->IER == 0)
|
||||
{
|
||||
plic_irq_unregister(IRQN_UART1_INTERRUPT + channel);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,176 +0,0 @@
|
||||
/* Copyright 2018 Canaan Inc.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* http://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.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include "uarths.h"
|
||||
#include "sysctl.h"
|
||||
#include "encoding.h"
|
||||
|
||||
volatile uarths_t *const uarths = (volatile uarths_t *)UARTHS_BASE_ADDR;
|
||||
|
||||
typedef struct _uarths_instance
|
||||
{
|
||||
plic_irq_callback_t callback;
|
||||
void *ctx;
|
||||
uarths_interrupt_mode_t uarths_interrupt_mode;
|
||||
} uarths_instance_t;
|
||||
|
||||
uarths_instance_t g_uarths_instance;
|
||||
|
||||
uarths_interrupt_mode_t uarths_get_interrupt_mode(void)
|
||||
{
|
||||
uint32_t v_rx_interrupt = uarths->ip.rxwm;
|
||||
uint32_t v_tx_interrupt = uarths->ip.txwm;
|
||||
return (v_rx_interrupt << 1) | v_tx_interrupt;
|
||||
}
|
||||
|
||||
int uarths_irq_callback(void *ctx)
|
||||
{
|
||||
uarths_instance_t *uart_context = (uarths_instance_t *)ctx;
|
||||
|
||||
if(uart_context->callback)
|
||||
uart_context->callback(uart_context->ctx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void uarths_set_interrupt_cnt(uarths_interrupt_mode_t interrupt_mode, uint8_t cnt)
|
||||
{
|
||||
switch(interrupt_mode)
|
||||
{
|
||||
case UARTHS_SEND:
|
||||
uarths->txctrl.txcnt = cnt;
|
||||
break;
|
||||
case UARTHS_RECEIVE:
|
||||
uarths->rxctrl.rxcnt = cnt;
|
||||
break;
|
||||
case UARTHS_SEND_RECEIVE:
|
||||
default:
|
||||
uarths->txctrl.txcnt = cnt;
|
||||
uarths->rxctrl.rxcnt = cnt;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void uarths_set_irq(uarths_interrupt_mode_t interrupt_mode, plic_irq_callback_t uarths_callback, void *ctx, uint32_t priority)
|
||||
{
|
||||
g_uarths_instance.callback = uarths_callback;
|
||||
g_uarths_instance.ctx = ctx;
|
||||
|
||||
switch(interrupt_mode)
|
||||
{
|
||||
case UARTHS_SEND:
|
||||
uarths->ie.txwm = 1;
|
||||
uarths->ie.rxwm = 0;
|
||||
break;
|
||||
case UARTHS_RECEIVE:
|
||||
uarths->ie.txwm = 0;
|
||||
uarths->ie.rxwm = 1;
|
||||
break;
|
||||
default:
|
||||
uarths->ie.txwm = 1;
|
||||
uarths->ie.rxwm = 1;
|
||||
break;
|
||||
}
|
||||
g_uarths_instance.uarths_interrupt_mode = interrupt_mode;
|
||||
|
||||
plic_set_priority(IRQN_UARTHS_INTERRUPT, priority);
|
||||
plic_irq_register(IRQN_UARTHS_INTERRUPT, uarths_irq_callback, &g_uarths_instance);
|
||||
plic_irq_enable(IRQN_UARTHS_INTERRUPT);
|
||||
}
|
||||
|
||||
static inline int uarths_putc(char c)
|
||||
{
|
||||
while (uarths->txdata.full)
|
||||
continue;
|
||||
uarths->txdata.data = (uint8_t)c;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t uarths_receive_data(uint8_t *buf, size_t buf_len)
|
||||
{
|
||||
size_t i;
|
||||
for(i = 0; i < buf_len; i++)
|
||||
{
|
||||
uarths_rxdata_t recv = uarths->rxdata;
|
||||
if(recv.empty)
|
||||
break;
|
||||
else
|
||||
buf[i] = (recv.data & 0xFF);
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
size_t uarths_send_data(const uint8_t *buf, size_t buf_len)
|
||||
{
|
||||
size_t write = 0;
|
||||
while (write < buf_len)
|
||||
{
|
||||
uarths_putc(*buf++);
|
||||
write++;
|
||||
}
|
||||
return write;
|
||||
}
|
||||
|
||||
int uarths_getc(void)
|
||||
{
|
||||
/* while not empty */
|
||||
uarths_rxdata_t recv = uarths->rxdata;
|
||||
|
||||
if (recv.empty)
|
||||
return EOF;
|
||||
else
|
||||
return recv.data;
|
||||
}
|
||||
|
||||
int uarths_putchar(char c)
|
||||
{
|
||||
return uarths_putc(c);
|
||||
}
|
||||
|
||||
int uarths_puts(const char *s)
|
||||
{
|
||||
while (*s)
|
||||
if (uarths_putc(*s++) != 0)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void uarths_init(void)
|
||||
{
|
||||
uint32_t freq = sysctl_clock_get_freq(SYSCTL_CLOCK_CPU);
|
||||
uint16_t div = freq / 115200 - 1;
|
||||
|
||||
/* Set UART registers */
|
||||
uarths->div.div = div;
|
||||
uarths->txctrl.txen = 1;
|
||||
uarths->rxctrl.rxen = 1;
|
||||
uarths->txctrl.txcnt = 0;
|
||||
uarths->rxctrl.rxcnt = 0;
|
||||
uarths->ip.txwm = 1;
|
||||
uarths->ip.rxwm = 1;
|
||||
uarths->ie.txwm = 0;
|
||||
uarths->ie.rxwm = 1;
|
||||
}
|
||||
|
||||
void uarths_config(uint32_t baud_rate, uarths_stopbit_t stopbit)
|
||||
{
|
||||
uint32_t freq = sysctl_clock_get_freq(SYSCTL_CLOCK_CPU);
|
||||
uint16_t div = freq / baud_rate - 1;
|
||||
uarths->div.div = div;
|
||||
uarths->txctrl.nstop = stopbit;
|
||||
}
|
||||
|
||||
@@ -1,44 +0,0 @@
|
||||
/* Copyright 2018 Canaan Inc.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* http://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.
|
||||
*/
|
||||
#include <stddef.h>
|
||||
#include "encoding.h"
|
||||
#include "utils.h"
|
||||
|
||||
void set_bit(volatile uint32_t *bits, uint32_t mask, uint32_t value)
|
||||
{
|
||||
uint32_t org = (*bits) & ~mask;
|
||||
*bits = org | (value & mask);
|
||||
}
|
||||
|
||||
void set_bit_offset(volatile uint32_t *bits, uint32_t mask, size_t offset, uint32_t value)
|
||||
{
|
||||
set_bit(bits, mask << offset, value << offset);
|
||||
}
|
||||
|
||||
void set_gpio_bit(volatile uint32_t *bits, size_t offset, uint32_t value)
|
||||
{
|
||||
set_bit_offset(bits, 1, offset, value);
|
||||
}
|
||||
|
||||
uint32_t get_bit(volatile uint32_t *bits, uint32_t mask, size_t offset)
|
||||
{
|
||||
return ((*bits) & (mask << offset)) >> offset;
|
||||
}
|
||||
|
||||
uint32_t get_gpio_bit(volatile uint32_t *bits, size_t offset)
|
||||
{
|
||||
return get_bit(bits, 1, offset);
|
||||
}
|
||||
|
||||
@@ -1,115 +0,0 @@
|
||||
/* Copyright 2018 Canaan Inc.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* http://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.
|
||||
*/
|
||||
#include "wdt.h"
|
||||
#include "platform.h"
|
||||
#include "stddef.h"
|
||||
#include "utils.h"
|
||||
#include "sysctl.h"
|
||||
#include "plic.h"
|
||||
#include "math.h"
|
||||
|
||||
volatile wdt_t *const wdt[2] =
|
||||
{
|
||||
(volatile wdt_t *)WDT0_BASE_ADDR,
|
||||
(volatile wdt_t *)WDT1_BASE_ADDR
|
||||
};
|
||||
|
||||
static void wdt_enable(wdt_device_number_t id)
|
||||
{
|
||||
wdt[id]->crr = WDT_CRR_MASK;
|
||||
wdt[id]->cr |= WDT_CR_ENABLE;
|
||||
}
|
||||
|
||||
static void wdt_disable(wdt_device_number_t id)
|
||||
{
|
||||
wdt[id]->crr = WDT_CRR_MASK;
|
||||
wdt[id]->cr &= (~WDT_CR_ENABLE);
|
||||
}
|
||||
|
||||
static void wdt_set_timeout(wdt_device_number_t id, uint8_t timeout)
|
||||
{
|
||||
wdt[id]->torr = WDT_TORR_TOP(timeout);
|
||||
}
|
||||
|
||||
static void wdt_response_mode(wdt_device_number_t id, uint8_t mode)
|
||||
{
|
||||
wdt[id]->cr &= (~WDT_CR_RMOD_MASK);
|
||||
wdt[id]->cr |= mode;
|
||||
}
|
||||
|
||||
static uint64_t wdt_get_pclk(wdt_device_number_t id)
|
||||
{
|
||||
return id ? sysctl_clock_get_freq(SYSCTL_CLOCK_WDT1) : sysctl_clock_get_freq(SYSCTL_CLOCK_WDT0);
|
||||
}
|
||||
|
||||
static uint8_t wdt_get_top(wdt_device_number_t id, uint64_t timeout_ms)
|
||||
{
|
||||
uint64_t wdt_clk = wdt_get_pclk(id);
|
||||
uint64_t ret = (timeout_ms * wdt_clk / 1000) >> 16;
|
||||
if (ret)
|
||||
ret = (uint32_t)log2(ret);
|
||||
if (ret > 0xf)
|
||||
ret = 0xf;
|
||||
return (uint8_t)ret;
|
||||
}
|
||||
|
||||
void wdt_feed(wdt_device_number_t id)
|
||||
{
|
||||
wdt[id]->crr = WDT_CRR_MASK;
|
||||
}
|
||||
|
||||
void wdt_clear_interrupt(wdt_device_number_t id)
|
||||
{
|
||||
wdt[id]->eoi = wdt[id]->eoi;
|
||||
}
|
||||
|
||||
void wdt_start(wdt_device_number_t id, uint64_t time_out_ms, plic_irq_callback_t on_irq)
|
||||
{
|
||||
sysctl_reset(id ? SYSCTL_RESET_WDT1 : SYSCTL_RESET_WDT0);
|
||||
sysctl_clock_set_threshold(id ? SYSCTL_THRESHOLD_WDT1 : SYSCTL_THRESHOLD_WDT0, 0);
|
||||
sysctl_clock_enable(id ? SYSCTL_CLOCK_WDT1 : SYSCTL_CLOCK_WDT0);
|
||||
|
||||
plic_set_priority(id ? IRQN_WDT1_INTERRUPT : IRQN_WDT0_INTERRUPT, 1);
|
||||
plic_irq_enable(id ? IRQN_WDT1_INTERRUPT : IRQN_WDT0_INTERRUPT);
|
||||
plic_irq_register(id ? IRQN_WDT1_INTERRUPT : IRQN_WDT0_INTERRUPT, on_irq, NULL);
|
||||
|
||||
wdt_response_mode(id, WDT_CR_RMOD_INTERRUPT);
|
||||
uint8_t m_top = wdt_get_top(id, time_out_ms);
|
||||
wdt_set_timeout(id, m_top);
|
||||
wdt_enable(id);
|
||||
}
|
||||
|
||||
uint32_t wdt_init(wdt_device_number_t id, uint64_t time_out_ms, plic_irq_callback_t on_irq, void *ctx)
|
||||
{
|
||||
sysctl_reset(id ? SYSCTL_RESET_WDT1 : SYSCTL_RESET_WDT0);
|
||||
sysctl_clock_set_threshold(id ? SYSCTL_THRESHOLD_WDT1 : SYSCTL_THRESHOLD_WDT0, 0);
|
||||
sysctl_clock_enable(id ? SYSCTL_CLOCK_WDT1 : SYSCTL_CLOCK_WDT0);
|
||||
|
||||
plic_set_priority(id ? IRQN_WDT1_INTERRUPT : IRQN_WDT0_INTERRUPT, 1);
|
||||
plic_irq_enable(id ? IRQN_WDT1_INTERRUPT : IRQN_WDT0_INTERRUPT);
|
||||
plic_irq_register(id ? IRQN_WDT1_INTERRUPT : IRQN_WDT0_INTERRUPT, on_irq, ctx);
|
||||
|
||||
wdt_response_mode(id, WDT_CR_RMOD_INTERRUPT);
|
||||
uint8_t m_top = wdt_get_top(id, time_out_ms);
|
||||
wdt_set_timeout(id, m_top);
|
||||
wdt_enable(id);
|
||||
return (1UL << (m_top + 16 + 1)) * 1000UL / wdt_get_pclk(id);
|
||||
}
|
||||
|
||||
void wdt_stop(wdt_device_number_t id)
|
||||
{
|
||||
wdt_disable(id);
|
||||
}
|
||||
|
||||
@@ -1,142 +0,0 @@
|
||||
/* Copyright 2018 Canaan Inc.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* http://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.
|
||||
*/
|
||||
/*
|
||||
* FreeRTOS Kernel V10.0.1
|
||||
* Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* http://www.FreeRTOS.org
|
||||
* http://aws.amazon.com/freertos
|
||||
*
|
||||
* 1 tab == 4 spaces!
|
||||
*/
|
||||
|
||||
|
||||
#ifndef FREERTOS_CONFIG_H
|
||||
#define FREERTOS_CONFIG_H
|
||||
/*-----------------------------------------------------------
|
||||
* Application specific definitions.
|
||||
*
|
||||
* These definitions should be adjusted for your particular hardware and
|
||||
* application requirements.
|
||||
*
|
||||
* THESE PARAMETERS ARE DESCRIBED WITHIN THE 'CONFIGURATION' SECTION OF THE
|
||||
* FreeRTOS API DOCUMENTATION AVAILABLE ON THE FreeRTOS.org WEB SITE.
|
||||
*
|
||||
* See http://www.freertos.org/a00110.html.
|
||||
*----------------------------------------------------------*/
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/* clock */
|
||||
#define configCPU_CLOCK_HZ uxPortGetCPUClock()
|
||||
#define configTICK_CLOCK_HZ ( configCPU_CLOCK_HZ / 50 )
|
||||
#define configTICK_RATE_HZ ( ( TickType_t ) 100 )
|
||||
|
||||
/* multithreading */
|
||||
#define configUSE_NEWLIB_REENTRANT 1
|
||||
|
||||
#define configUSE_PREEMPTION 1
|
||||
#define configUSE_PORT_OPTIMISED_TASK_SELECTION 0
|
||||
#define configMAX_PRIORITIES ( 5 )
|
||||
#define configMAX_TASK_NAME_LEN ( 16 )
|
||||
#define configUSE_TRACE_FACILITY 0
|
||||
#define configUSE_16_BIT_TICKS 0
|
||||
#define configIDLE_SHOULD_YIELD 0
|
||||
#define configQUEUE_REGISTRY_SIZE 8
|
||||
|
||||
/* TLS */
|
||||
enum
|
||||
{
|
||||
PTHREAD_TLS_INDEX = 0
|
||||
};
|
||||
|
||||
#define configNUM_THREAD_LOCAL_STORAGE_POINTERS 1
|
||||
|
||||
/* mutex */
|
||||
#define configUSE_MUTEXES 1
|
||||
#define configUSE_RECURSIVE_MUTEXES 1
|
||||
|
||||
/* hooks */
|
||||
#define configUSE_MALLOC_FAILED_HOOK 0
|
||||
#define configUSE_IDLE_HOOK 1
|
||||
#define configUSE_TICK_HOOK 0
|
||||
#define configUSE_DAEMON_TASK_STARTUP_HOOK 0
|
||||
|
||||
/* memory */
|
||||
#define configMINIMAL_STACK_SIZE ( ( unsigned short ) 2048 )
|
||||
#define configTOTAL_HEAP_SIZE ( ( size_t ) ( 1024 * 512 ) )
|
||||
#define configSUPPORT_STATIC_ALLOCATION 1
|
||||
#define configSUPPORT_DYNAMIC_ALLOCATION 1
|
||||
|
||||
#define configUSE_APPLICATION_TASK_TAG 1
|
||||
#define configUSE_COUNTING_SEMAPHORES 1
|
||||
#define configUSE_TICKLESS_IDLE 1
|
||||
#define configGENERATE_RUN_TIME_STATS 0
|
||||
#define configUSE_STATS_FORMATTING_FUNCTIONS 1
|
||||
|
||||
/* Co-routine definitions. */
|
||||
#define configUSE_CO_ROUTINES 0
|
||||
#define configMAX_CO_ROUTINE_PRIORITIES ( 2 )
|
||||
|
||||
/* Software timer definitions. */
|
||||
#define configUSE_TIMERS 0
|
||||
#define configTIMER_TASK_PRIORITY ( 2 )
|
||||
#define configTIMER_QUEUE_LENGTH 2
|
||||
#define configTIMER_TASK_STACK_DEPTH ( configMINIMAL_STACK_SIZE )
|
||||
|
||||
/* Set the following definitions to 1 to include the API function, or zero to exclude the API function. */
|
||||
#define INCLUDE_vTaskPrioritySet 1
|
||||
#define INCLUDE_uxTaskPriorityGet 1
|
||||
#define INCLUDE_vTaskDelete 1
|
||||
#define INCLUDE_vTaskCleanUpResources 1
|
||||
#define INCLUDE_vTaskSuspend 1
|
||||
#define INCLUDE_vTaskDelayUntil 1
|
||||
#define INCLUDE_vTaskDelay 1
|
||||
#define INCLUDE_eTaskGetState 1
|
||||
#define INCLUDE_xTaskAbortDelay 1
|
||||
|
||||
#define INCLUDE_xSemaphoreGetMutexHolder 1
|
||||
|
||||
/* Diagnostics */
|
||||
#define configCHECK_FOR_STACK_OVERFLOW 1
|
||||
|
||||
#ifdef configASSERT
|
||||
#undef configASSERT
|
||||
#endif
|
||||
/* configASSERT behaviour */
|
||||
extern void vPortFatal(const char* file, int line, const char* message);
|
||||
/* Normal assert() semantics without relying on the provision of an assert.h header file. */
|
||||
#define configASSERT( x ) if( ( x ) == 0 ) { \
|
||||
vPortFatal(__FILE__, __LINE__, #x); \
|
||||
}
|
||||
|
||||
#endif /* FREERTOS_CONFIG_H */
|
||||
@@ -1,100 +0,0 @@
|
||||
/* Copyright 2018 Canaan Inc.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* http://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.
|
||||
*/
|
||||
#include <atomic.h>
|
||||
#include <clint.h>
|
||||
#include <core_sync.h>
|
||||
#include <encoding.h>
|
||||
#include <plic.h>
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
|
||||
volatile UBaseType_t g_core_pending_switch[portNUM_PROCESSORS] = { 0 };
|
||||
static volatile UBaseType_t s_core_sync_events[portNUM_PROCESSORS] = { 0 };
|
||||
static volatile TaskHandle_t s_pending_to_add_tasks[portNUM_PROCESSORS] = { 0 };
|
||||
static volatile UBaseType_t s_core_sync_in_progress[portNUM_PROCESSORS] = { 0 };
|
||||
|
||||
uintptr_t handle_irq_m_soft(uintptr_t cause, uintptr_t epc, uintptr_t regs[32], uintptr_t fregs[32])
|
||||
{
|
||||
uint64_t core_id = uxPortGetProcessorId();
|
||||
atomic_set(&s_core_sync_in_progress[core_id], 1);
|
||||
switch (s_core_sync_events[core_id])
|
||||
{
|
||||
case CORE_SYNC_ADD_TCB:
|
||||
{
|
||||
TaskHandle_t newTask = atomic_read(&s_pending_to_add_tasks[core_id]);
|
||||
if (newTask)
|
||||
{
|
||||
vAddNewTaskToCurrentReadyList(newTask);
|
||||
atomic_set(&s_pending_to_add_tasks[core_id], NULL);
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
core_sync_complete(core_id);
|
||||
return epc;
|
||||
}
|
||||
|
||||
uintptr_t handle_irq_m_timer(uintptr_t cause, uintptr_t epc, uintptr_t regs[32], uintptr_t fregs[32])
|
||||
{
|
||||
prvSetNextTimerInterrupt();
|
||||
|
||||
/* Increment the RTOS tick. */
|
||||
if (xTaskIncrementTick() != pdFALSE)
|
||||
{
|
||||
core_sync_request_context_switch(uxPortGetProcessorId());
|
||||
}
|
||||
|
||||
return epc;
|
||||
}
|
||||
|
||||
void core_sync_request_context_switch(uint64_t core_id)
|
||||
{
|
||||
atomic_set(&g_core_pending_switch[core_id], 1);
|
||||
clint_ipi_send(core_id);
|
||||
}
|
||||
|
||||
void core_sync_complete(uint64_t core_id)
|
||||
{
|
||||
if (atomic_read(&g_core_pending_switch[core_id]) == 0)
|
||||
clint_ipi_clear(core_id);
|
||||
atomic_set(&s_core_sync_events[core_id], CORE_SYNC_NONE);
|
||||
atomic_set(&s_core_sync_in_progress[core_id], 0);
|
||||
}
|
||||
|
||||
void core_sync_complete_context_switch(uint64_t core_id)
|
||||
{
|
||||
if (atomic_read(&s_core_sync_events[core_id]) == CORE_SYNC_NONE)
|
||||
clint_ipi_clear(core_id);
|
||||
atomic_set(&g_core_pending_switch[core_id], 0);
|
||||
}
|
||||
|
||||
int core_sync_is_in_progress(uint64_t core_id)
|
||||
{
|
||||
return !!atomic_read(&s_core_sync_in_progress[core_id]);
|
||||
}
|
||||
|
||||
void vPortAddNewTaskToReadyListAsync(UBaseType_t uxPsrId, void* pxNewTaskHandle)
|
||||
{
|
||||
// Wait for last adding tcb complete
|
||||
while (atomic_read(&s_pending_to_add_tasks[uxPsrId]));
|
||||
atomic_set(&s_pending_to_add_tasks[uxPsrId], pxNewTaskHandle);
|
||||
|
||||
while (atomic_cas(&s_core_sync_events[uxPsrId], CORE_SYNC_NONE, CORE_SYNC_ADD_TCB) != CORE_SYNC_NONE)
|
||||
;
|
||||
clint_ipi_send(uxPsrId);
|
||||
}
|
||||
@@ -1,367 +0,0 @@
|
||||
/* Copyright 2018 Canaan Inc.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* http://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.
|
||||
*/
|
||||
/*
|
||||
* FreeRTOS Kernel V10.0.1
|
||||
* Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* http://www.FreeRTOS.org
|
||||
* http://aws.amazon.com/freertos
|
||||
*
|
||||
* 1 tab == 4 spaces!
|
||||
*/
|
||||
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
#include "croutine.h"
|
||||
|
||||
/* Remove the whole file is co-routines are not being used. */
|
||||
#if( configUSE_CO_ROUTINES != 0 )
|
||||
|
||||
/*
|
||||
* Some kernel aware debuggers require data to be viewed to be global, rather
|
||||
* than file scope.
|
||||
*/
|
||||
#ifdef portREMOVE_STATIC_QUALIFIER
|
||||
#define static
|
||||
#endif
|
||||
|
||||
|
||||
/* Lists for ready and blocked co-routines. --------------------*/
|
||||
static List_t pxReadyCoRoutineLists[ configMAX_CO_ROUTINE_PRIORITIES ]; /*< Prioritised ready co-routines. */
|
||||
static List_t xDelayedCoRoutineList1; /*< Delayed co-routines. */
|
||||
static List_t xDelayedCoRoutineList2; /*< Delayed co-routines (two lists are used - one for delays that have overflowed the current tick count. */
|
||||
static List_t * pxDelayedCoRoutineList; /*< Points to the delayed co-routine list currently being used. */
|
||||
static List_t * pxOverflowDelayedCoRoutineList; /*< Points to the delayed co-routine list currently being used to hold co-routines that have overflowed the current tick count. */
|
||||
static List_t xPendingReadyCoRoutineList; /*< Holds co-routines that have been readied by an external event. They cannot be added directly to the ready lists as the ready lists cannot be accessed by interrupts. */
|
||||
|
||||
/* Other file private variables. --------------------------------*/
|
||||
CRCB_t * pxCurrentCoRoutine = NULL;
|
||||
static UBaseType_t uxTopCoRoutineReadyPriority = 0;
|
||||
static TickType_t xCoRoutineTickCount = 0, xLastTickCount = 0, xPassedTicks = 0;
|
||||
|
||||
/* The initial state of the co-routine when it is created. */
|
||||
#define corINITIAL_STATE ( 0 )
|
||||
|
||||
/*
|
||||
* Place the co-routine represented by pxCRCB into the appropriate ready queue
|
||||
* for the priority. It is inserted at the end of the list.
|
||||
*
|
||||
* This macro accesses the co-routine ready lists and therefore must not be
|
||||
* used from within an ISR.
|
||||
*/
|
||||
#define prvAddCoRoutineToReadyQueue( pxCRCB ) \
|
||||
{ \
|
||||
if( pxCRCB->uxPriority > uxTopCoRoutineReadyPriority ) \
|
||||
{ \
|
||||
uxTopCoRoutineReadyPriority = pxCRCB->uxPriority; \
|
||||
} \
|
||||
vListInsertEnd( ( List_t * ) &( pxReadyCoRoutineLists[ pxCRCB->uxPriority ] ), &( pxCRCB->xGenericListItem ) ); \
|
||||
}
|
||||
|
||||
/*
|
||||
* Utility to ready all the lists used by the scheduler. This is called
|
||||
* automatically upon the creation of the first co-routine.
|
||||
*/
|
||||
static void prvInitialiseCoRoutineLists( void );
|
||||
|
||||
/*
|
||||
* Co-routines that are readied by an interrupt cannot be placed directly into
|
||||
* the ready lists (there is no mutual exclusion). Instead they are placed in
|
||||
* in the pending ready list in order that they can later be moved to the ready
|
||||
* list by the co-routine scheduler.
|
||||
*/
|
||||
static void prvCheckPendingReadyList( void );
|
||||
|
||||
/*
|
||||
* Macro that looks at the list of co-routines that are currently delayed to
|
||||
* see if any require waking.
|
||||
*
|
||||
* Co-routines are stored in the queue in the order of their wake time -
|
||||
* meaning once one co-routine has been found whose timer has not expired
|
||||
* we need not look any further down the list.
|
||||
*/
|
||||
static void prvCheckDelayedList( void );
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
BaseType_t xCoRoutineCreate( crCOROUTINE_CODE pxCoRoutineCode, UBaseType_t uxPriority, UBaseType_t uxIndex )
|
||||
{
|
||||
BaseType_t xReturn;
|
||||
CRCB_t *pxCoRoutine;
|
||||
|
||||
/* Allocate the memory that will store the co-routine control block. */
|
||||
pxCoRoutine = ( CRCB_t * ) pvPortMalloc( sizeof( CRCB_t ) );
|
||||
if( pxCoRoutine )
|
||||
{
|
||||
/* If pxCurrentCoRoutine is NULL then this is the first co-routine to
|
||||
be created and the co-routine data structures need initialising. */
|
||||
if( pxCurrentCoRoutine == NULL )
|
||||
{
|
||||
pxCurrentCoRoutine = pxCoRoutine;
|
||||
prvInitialiseCoRoutineLists();
|
||||
}
|
||||
|
||||
/* Check the priority is within limits. */
|
||||
if( uxPriority >= configMAX_CO_ROUTINE_PRIORITIES )
|
||||
{
|
||||
uxPriority = configMAX_CO_ROUTINE_PRIORITIES - 1;
|
||||
}
|
||||
|
||||
/* Fill out the co-routine control block from the function parameters. */
|
||||
pxCoRoutine->uxState = corINITIAL_STATE;
|
||||
pxCoRoutine->uxPriority = uxPriority;
|
||||
pxCoRoutine->uxIndex = uxIndex;
|
||||
pxCoRoutine->pxCoRoutineFunction = pxCoRoutineCode;
|
||||
|
||||
/* Initialise all the other co-routine control block parameters. */
|
||||
vListInitialiseItem( &( pxCoRoutine->xGenericListItem ) );
|
||||
vListInitialiseItem( &( pxCoRoutine->xEventListItem ) );
|
||||
|
||||
/* Set the co-routine control block as a link back from the ListItem_t.
|
||||
This is so we can get back to the containing CRCB from a generic item
|
||||
in a list. */
|
||||
listSET_LIST_ITEM_OWNER( &( pxCoRoutine->xGenericListItem ), pxCoRoutine );
|
||||
listSET_LIST_ITEM_OWNER( &( pxCoRoutine->xEventListItem ), pxCoRoutine );
|
||||
|
||||
/* Event lists are always in priority order. */
|
||||
listSET_LIST_ITEM_VALUE( &( pxCoRoutine->xEventListItem ), ( ( TickType_t ) configMAX_CO_ROUTINE_PRIORITIES - ( TickType_t ) uxPriority ) );
|
||||
|
||||
/* Now the co-routine has been initialised it can be added to the ready
|
||||
list at the correct priority. */
|
||||
prvAddCoRoutineToReadyQueue( pxCoRoutine );
|
||||
|
||||
xReturn = pdPASS;
|
||||
}
|
||||
else
|
||||
{
|
||||
xReturn = errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY;
|
||||
}
|
||||
|
||||
return xReturn;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vCoRoutineAddToDelayedList( TickType_t xTicksToDelay, List_t *pxEventList )
|
||||
{
|
||||
TickType_t xTimeToWake;
|
||||
|
||||
/* Calculate the time to wake - this may overflow but this is
|
||||
not a problem. */
|
||||
xTimeToWake = xCoRoutineTickCount + xTicksToDelay;
|
||||
|
||||
/* We must remove ourselves from the ready list before adding
|
||||
ourselves to the blocked list as the same list item is used for
|
||||
both lists. */
|
||||
( void ) uxListRemove( ( ListItem_t * ) &( pxCurrentCoRoutine->xGenericListItem ) );
|
||||
|
||||
/* The list item will be inserted in wake time order. */
|
||||
listSET_LIST_ITEM_VALUE( &( pxCurrentCoRoutine->xGenericListItem ), xTimeToWake );
|
||||
|
||||
if( xTimeToWake < xCoRoutineTickCount )
|
||||
{
|
||||
/* Wake time has overflowed. Place this item in the
|
||||
overflow list. */
|
||||
vListInsert( ( List_t * ) pxOverflowDelayedCoRoutineList, ( ListItem_t * ) &( pxCurrentCoRoutine->xGenericListItem ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
/* The wake time has not overflowed, so we can use the
|
||||
current block list. */
|
||||
vListInsert( ( List_t * ) pxDelayedCoRoutineList, ( ListItem_t * ) &( pxCurrentCoRoutine->xGenericListItem ) );
|
||||
}
|
||||
|
||||
if( pxEventList )
|
||||
{
|
||||
/* Also add the co-routine to an event list. If this is done then the
|
||||
function must be called with interrupts disabled. */
|
||||
vListInsert( pxEventList, &( pxCurrentCoRoutine->xEventListItem ) );
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static void prvCheckPendingReadyList( void )
|
||||
{
|
||||
/* Are there any co-routines waiting to get moved to the ready list? These
|
||||
are co-routines that have been readied by an ISR. The ISR cannot access
|
||||
the ready lists itself. */
|
||||
while( listLIST_IS_EMPTY( &xPendingReadyCoRoutineList ) == pdFALSE )
|
||||
{
|
||||
CRCB_t *pxUnblockedCRCB;
|
||||
|
||||
/* The pending ready list can be accessed by an ISR. */
|
||||
portDISABLE_INTERRUPTS();
|
||||
{
|
||||
pxUnblockedCRCB = ( CRCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( (&xPendingReadyCoRoutineList) );
|
||||
( void ) uxListRemove( &( pxUnblockedCRCB->xEventListItem ) );
|
||||
}
|
||||
portENABLE_INTERRUPTS();
|
||||
|
||||
( void ) uxListRemove( &( pxUnblockedCRCB->xGenericListItem ) );
|
||||
prvAddCoRoutineToReadyQueue( pxUnblockedCRCB );
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static void prvCheckDelayedList( void )
|
||||
{
|
||||
CRCB_t *pxCRCB;
|
||||
|
||||
xPassedTicks = xTaskGetTickCount() - xLastTickCount;
|
||||
while( xPassedTicks )
|
||||
{
|
||||
xCoRoutineTickCount++;
|
||||
xPassedTicks--;
|
||||
|
||||
/* If the tick count has overflowed we need to swap the ready lists. */
|
||||
if( xCoRoutineTickCount == 0 )
|
||||
{
|
||||
List_t * pxTemp;
|
||||
|
||||
/* Tick count has overflowed so we need to swap the delay lists. If there are
|
||||
any items in pxDelayedCoRoutineList here then there is an error! */
|
||||
pxTemp = pxDelayedCoRoutineList;
|
||||
pxDelayedCoRoutineList = pxOverflowDelayedCoRoutineList;
|
||||
pxOverflowDelayedCoRoutineList = pxTemp;
|
||||
}
|
||||
|
||||
/* See if this tick has made a timeout expire. */
|
||||
while( listLIST_IS_EMPTY( pxDelayedCoRoutineList ) == pdFALSE )
|
||||
{
|
||||
pxCRCB = ( CRCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( pxDelayedCoRoutineList );
|
||||
|
||||
if( xCoRoutineTickCount < listGET_LIST_ITEM_VALUE( &( pxCRCB->xGenericListItem ) ) )
|
||||
{
|
||||
/* Timeout not yet expired. */
|
||||
break;
|
||||
}
|
||||
|
||||
portDISABLE_INTERRUPTS();
|
||||
{
|
||||
/* The event could have occurred just before this critical
|
||||
section. If this is the case then the generic list item will
|
||||
have been moved to the pending ready list and the following
|
||||
line is still valid. Also the pvContainer parameter will have
|
||||
been set to NULL so the following lines are also valid. */
|
||||
( void ) uxListRemove( &( pxCRCB->xGenericListItem ) );
|
||||
|
||||
/* Is the co-routine waiting on an event also? */
|
||||
if( pxCRCB->xEventListItem.pvContainer )
|
||||
{
|
||||
( void ) uxListRemove( &( pxCRCB->xEventListItem ) );
|
||||
}
|
||||
}
|
||||
portENABLE_INTERRUPTS();
|
||||
|
||||
prvAddCoRoutineToReadyQueue( pxCRCB );
|
||||
}
|
||||
}
|
||||
|
||||
xLastTickCount = xCoRoutineTickCount;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vCoRoutineSchedule( void )
|
||||
{
|
||||
/* See if any co-routines readied by events need moving to the ready lists. */
|
||||
prvCheckPendingReadyList();
|
||||
|
||||
/* See if any delayed co-routines have timed out. */
|
||||
prvCheckDelayedList();
|
||||
|
||||
/* Find the highest priority queue that contains ready co-routines. */
|
||||
while( listLIST_IS_EMPTY( &( pxReadyCoRoutineLists[ uxTopCoRoutineReadyPriority ] ) ) )
|
||||
{
|
||||
if( uxTopCoRoutineReadyPriority == 0 )
|
||||
{
|
||||
/* No more co-routines to check. */
|
||||
return;
|
||||
}
|
||||
--uxTopCoRoutineReadyPriority;
|
||||
}
|
||||
|
||||
/* listGET_OWNER_OF_NEXT_ENTRY walks through the list, so the co-routines
|
||||
of the same priority get an equal share of the processor time. */
|
||||
listGET_OWNER_OF_NEXT_ENTRY( pxCurrentCoRoutine, &( pxReadyCoRoutineLists[ uxTopCoRoutineReadyPriority ] ) );
|
||||
|
||||
/* Call the co-routine. */
|
||||
( pxCurrentCoRoutine->pxCoRoutineFunction )( pxCurrentCoRoutine, pxCurrentCoRoutine->uxIndex );
|
||||
|
||||
return;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static void prvInitialiseCoRoutineLists( void )
|
||||
{
|
||||
UBaseType_t uxPriority;
|
||||
|
||||
for( uxPriority = 0; uxPriority < configMAX_CO_ROUTINE_PRIORITIES; uxPriority++ )
|
||||
{
|
||||
vListInitialise( ( List_t * ) &( pxReadyCoRoutineLists[ uxPriority ] ) );
|
||||
}
|
||||
|
||||
vListInitialise( ( List_t * ) &xDelayedCoRoutineList1 );
|
||||
vListInitialise( ( List_t * ) &xDelayedCoRoutineList2 );
|
||||
vListInitialise( ( List_t * ) &xPendingReadyCoRoutineList );
|
||||
|
||||
/* Start with pxDelayedCoRoutineList using list1 and the
|
||||
pxOverflowDelayedCoRoutineList using list2. */
|
||||
pxDelayedCoRoutineList = &xDelayedCoRoutineList1;
|
||||
pxOverflowDelayedCoRoutineList = &xDelayedCoRoutineList2;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
BaseType_t xCoRoutineRemoveFromEventList( const List_t *pxEventList )
|
||||
{
|
||||
CRCB_t *pxUnblockedCRCB;
|
||||
BaseType_t xReturn;
|
||||
|
||||
/* This function is called from within an interrupt. It can only access
|
||||
event lists and the pending ready list. This function assumes that a
|
||||
check has already been made to ensure pxEventList is not empty. */
|
||||
pxUnblockedCRCB = ( CRCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( pxEventList );
|
||||
( void ) uxListRemove( &( pxUnblockedCRCB->xEventListItem ) );
|
||||
vListInsertEnd( ( List_t * ) &( xPendingReadyCoRoutineList ), &( pxUnblockedCRCB->xEventListItem ) );
|
||||
|
||||
if( pxUnblockedCRCB->uxPriority >= pxCurrentCoRoutine->uxPriority )
|
||||
{
|
||||
xReturn = pdTRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
xReturn = pdFALSE;
|
||||
}
|
||||
|
||||
return xReturn;
|
||||
}
|
||||
|
||||
#endif /* configUSE_CO_ROUTINES == 0 */
|
||||
|
||||
@@ -1,752 +0,0 @@
|
||||
/* Copyright 2018 Canaan Inc.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* http://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.
|
||||
*/
|
||||
/*
|
||||
* FreeRTOS Kernel V10.0.1
|
||||
* Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* http://www.FreeRTOS.org
|
||||
* http://aws.amazon.com/freertos
|
||||
*
|
||||
* 1 tab == 4 spaces!
|
||||
*/
|
||||
|
||||
/* Standard includes. */
|
||||
#include <stdlib.h>
|
||||
|
||||
/* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining
|
||||
all the API functions to use the MPU wrappers. That should only be done when
|
||||
task.h is included from an application file. */
|
||||
#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE
|
||||
|
||||
/* FreeRTOS includes. */
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
#include "timers.h"
|
||||
#include "event_groups.h"
|
||||
|
||||
/* Lint e961 and e750 are suppressed as a MISRA exception justified because the
|
||||
MPU ports require MPU_WRAPPERS_INCLUDED_FROM_API_FILE to be defined for the
|
||||
header files above, but not in this file, in order to generate the correct
|
||||
privileged Vs unprivileged linkage and placement. */
|
||||
#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE /*lint !e961 !e750. */
|
||||
|
||||
/* The following bit fields convey control information in a task's event list
|
||||
item value. It is important they don't clash with the
|
||||
taskEVENT_LIST_ITEM_VALUE_IN_USE definition. */
|
||||
#if configUSE_16_BIT_TICKS == 1
|
||||
#define eventCLEAR_EVENTS_ON_EXIT_BIT 0x0100U
|
||||
#define eventUNBLOCKED_DUE_TO_BIT_SET 0x0200U
|
||||
#define eventWAIT_FOR_ALL_BITS 0x0400U
|
||||
#define eventEVENT_BITS_CONTROL_BYTES 0xff00U
|
||||
#else
|
||||
#define eventCLEAR_EVENTS_ON_EXIT_BIT 0x01000000UL
|
||||
#define eventUNBLOCKED_DUE_TO_BIT_SET 0x02000000UL
|
||||
#define eventWAIT_FOR_ALL_BITS 0x04000000UL
|
||||
#define eventEVENT_BITS_CONTROL_BYTES 0xff000000UL
|
||||
#endif
|
||||
|
||||
typedef struct xEventGroupDefinition
|
||||
{
|
||||
EventBits_t uxEventBits;
|
||||
List_t xTasksWaitingForBits; /*< List of tasks waiting for a bit to be set. */
|
||||
|
||||
#if( configUSE_TRACE_FACILITY == 1 )
|
||||
UBaseType_t uxEventGroupNumber;
|
||||
#endif
|
||||
|
||||
#if( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) )
|
||||
uint8_t ucStaticallyAllocated; /*< Set to pdTRUE if the event group is statically allocated to ensure no attempt is made to free the memory. */
|
||||
#endif
|
||||
} EventGroup_t;
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* Test the bits set in uxCurrentEventBits to see if the wait condition is met.
|
||||
* The wait condition is defined by xWaitForAllBits. If xWaitForAllBits is
|
||||
* pdTRUE then the wait condition is met if all the bits set in uxBitsToWaitFor
|
||||
* are also set in uxCurrentEventBits. If xWaitForAllBits is pdFALSE then the
|
||||
* wait condition is met if any of the bits set in uxBitsToWait for are also set
|
||||
* in uxCurrentEventBits.
|
||||
*/
|
||||
static BaseType_t prvTestWaitCondition( const EventBits_t uxCurrentEventBits, const EventBits_t uxBitsToWaitFor, const BaseType_t xWaitForAllBits ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if( configSUPPORT_STATIC_ALLOCATION == 1 )
|
||||
|
||||
EventGroupHandle_t xEventGroupCreateStatic( StaticEventGroup_t *pxEventGroupBuffer )
|
||||
{
|
||||
EventGroup_t *pxEventBits;
|
||||
|
||||
/* A StaticEventGroup_t object must be provided. */
|
||||
configASSERT( pxEventGroupBuffer );
|
||||
|
||||
#if( configASSERT_DEFINED == 1 )
|
||||
{
|
||||
/* Sanity check that the size of the structure used to declare a
|
||||
variable of type StaticEventGroup_t equals the size of the real
|
||||
event group structure. */
|
||||
volatile size_t xSize = sizeof( StaticEventGroup_t );
|
||||
configASSERT( xSize == sizeof( EventGroup_t ) );
|
||||
}
|
||||
#endif /* configASSERT_DEFINED */
|
||||
|
||||
/* The user has provided a statically allocated event group - use it. */
|
||||
pxEventBits = ( EventGroup_t * ) pxEventGroupBuffer; /*lint !e740 EventGroup_t and StaticEventGroup_t are guaranteed to have the same size and alignment requirement - checked by configASSERT(). */
|
||||
|
||||
if( pxEventBits != NULL )
|
||||
{
|
||||
pxEventBits->uxEventBits = 0;
|
||||
vListInitialise( &( pxEventBits->xTasksWaitingForBits ) );
|
||||
|
||||
#if( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
|
||||
{
|
||||
/* Both static and dynamic allocation can be used, so note that
|
||||
this event group was created statically in case the event group
|
||||
is later deleted. */
|
||||
pxEventBits->ucStaticallyAllocated = pdTRUE;
|
||||
}
|
||||
#endif /* configSUPPORT_DYNAMIC_ALLOCATION */
|
||||
|
||||
traceEVENT_GROUP_CREATE( pxEventBits );
|
||||
}
|
||||
else
|
||||
{
|
||||
traceEVENT_GROUP_CREATE_FAILED();
|
||||
}
|
||||
|
||||
return ( EventGroupHandle_t ) pxEventBits;
|
||||
}
|
||||
|
||||
#endif /* configSUPPORT_STATIC_ALLOCATION */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
|
||||
|
||||
EventGroupHandle_t xEventGroupCreate( void )
|
||||
{
|
||||
EventGroup_t *pxEventBits;
|
||||
|
||||
/* Allocate the event group. */
|
||||
pxEventBits = ( EventGroup_t * ) pvPortMalloc( sizeof( EventGroup_t ) );
|
||||
|
||||
if( pxEventBits != NULL )
|
||||
{
|
||||
pxEventBits->uxEventBits = 0;
|
||||
vListInitialise( &( pxEventBits->xTasksWaitingForBits ) );
|
||||
|
||||
#if( configSUPPORT_STATIC_ALLOCATION == 1 )
|
||||
{
|
||||
/* Both static and dynamic allocation can be used, so note this
|
||||
event group was allocated statically in case the event group is
|
||||
later deleted. */
|
||||
pxEventBits->ucStaticallyAllocated = pdFALSE;
|
||||
}
|
||||
#endif /* configSUPPORT_STATIC_ALLOCATION */
|
||||
|
||||
traceEVENT_GROUP_CREATE( pxEventBits );
|
||||
}
|
||||
else
|
||||
{
|
||||
traceEVENT_GROUP_CREATE_FAILED();
|
||||
}
|
||||
|
||||
return ( EventGroupHandle_t ) pxEventBits;
|
||||
}
|
||||
|
||||
#endif /* configSUPPORT_DYNAMIC_ALLOCATION */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
EventBits_t xEventGroupSync( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet, const EventBits_t uxBitsToWaitFor, TickType_t xTicksToWait )
|
||||
{
|
||||
EventBits_t uxOriginalBitValue, uxReturn;
|
||||
EventGroup_t *pxEventBits = ( EventGroup_t * ) xEventGroup;
|
||||
BaseType_t xAlreadyYielded;
|
||||
BaseType_t xTimeoutOccurred = pdFALSE;
|
||||
|
||||
configASSERT( ( uxBitsToWaitFor & eventEVENT_BITS_CONTROL_BYTES ) == 0 );
|
||||
configASSERT( uxBitsToWaitFor != 0 );
|
||||
#if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) )
|
||||
{
|
||||
configASSERT( !( ( xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED ) && ( xTicksToWait != 0 ) ) );
|
||||
}
|
||||
#endif
|
||||
|
||||
vTaskSuspendAll();
|
||||
{
|
||||
uxOriginalBitValue = pxEventBits->uxEventBits;
|
||||
|
||||
( void ) xEventGroupSetBits( xEventGroup, uxBitsToSet );
|
||||
|
||||
if( ( ( uxOriginalBitValue | uxBitsToSet ) & uxBitsToWaitFor ) == uxBitsToWaitFor )
|
||||
{
|
||||
/* All the rendezvous bits are now set - no need to block. */
|
||||
uxReturn = ( uxOriginalBitValue | uxBitsToSet );
|
||||
|
||||
/* Rendezvous always clear the bits. They will have been cleared
|
||||
already unless this is the only task in the rendezvous. */
|
||||
pxEventBits->uxEventBits &= ~uxBitsToWaitFor;
|
||||
|
||||
xTicksToWait = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( xTicksToWait != ( TickType_t ) 0 )
|
||||
{
|
||||
traceEVENT_GROUP_SYNC_BLOCK( xEventGroup, uxBitsToSet, uxBitsToWaitFor );
|
||||
|
||||
/* Store the bits that the calling task is waiting for in the
|
||||
task's event list item so the kernel knows when a match is
|
||||
found. Then enter the blocked state. */
|
||||
vTaskPlaceOnUnorderedEventList( &( pxEventBits->xTasksWaitingForBits ), ( uxBitsToWaitFor | eventCLEAR_EVENTS_ON_EXIT_BIT | eventWAIT_FOR_ALL_BITS ), xTicksToWait );
|
||||
|
||||
/* This assignment is obsolete as uxReturn will get set after
|
||||
the task unblocks, but some compilers mistakenly generate a
|
||||
warning about uxReturn being returned without being set if the
|
||||
assignment is omitted. */
|
||||
uxReturn = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* The rendezvous bits were not set, but no block time was
|
||||
specified - just return the current event bit value. */
|
||||
uxReturn = pxEventBits->uxEventBits;
|
||||
xTimeoutOccurred = pdTRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
xAlreadyYielded = xTaskResumeAll();
|
||||
|
||||
if( xTicksToWait != ( TickType_t ) 0 )
|
||||
{
|
||||
if( xAlreadyYielded == pdFALSE )
|
||||
{
|
||||
portYIELD_WITHIN_API();
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
|
||||
/* The task blocked to wait for its required bits to be set - at this
|
||||
point either the required bits were set or the block time expired. If
|
||||
the required bits were set they will have been stored in the task's
|
||||
event list item, and they should now be retrieved then cleared. */
|
||||
uxReturn = uxTaskResetEventItemValue();
|
||||
|
||||
if( ( uxReturn & eventUNBLOCKED_DUE_TO_BIT_SET ) == ( EventBits_t ) 0 )
|
||||
{
|
||||
/* The task timed out, just return the current event bit value. */
|
||||
taskENTER_CRITICAL();
|
||||
{
|
||||
uxReturn = pxEventBits->uxEventBits;
|
||||
|
||||
/* Although the task got here because it timed out before the
|
||||
bits it was waiting for were set, it is possible that since it
|
||||
unblocked another task has set the bits. If this is the case
|
||||
then it needs to clear the bits before exiting. */
|
||||
if( ( uxReturn & uxBitsToWaitFor ) == uxBitsToWaitFor )
|
||||
{
|
||||
pxEventBits->uxEventBits &= ~uxBitsToWaitFor;
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
}
|
||||
taskEXIT_CRITICAL();
|
||||
|
||||
xTimeoutOccurred = pdTRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* The task unblocked because the bits were set. */
|
||||
}
|
||||
|
||||
/* Control bits might be set as the task had blocked should not be
|
||||
returned. */
|
||||
uxReturn &= ~eventEVENT_BITS_CONTROL_BYTES;
|
||||
}
|
||||
|
||||
traceEVENT_GROUP_SYNC_END( xEventGroup, uxBitsToSet, uxBitsToWaitFor, xTimeoutOccurred );
|
||||
|
||||
/* Prevent compiler warnings when trace macros are not used. */
|
||||
( void ) xTimeoutOccurred;
|
||||
|
||||
return uxReturn;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
EventBits_t xEventGroupWaitBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToWaitFor, const BaseType_t xClearOnExit, const BaseType_t xWaitForAllBits, TickType_t xTicksToWait )
|
||||
{
|
||||
EventGroup_t *pxEventBits = ( EventGroup_t * ) xEventGroup;
|
||||
EventBits_t uxReturn, uxControlBits = 0;
|
||||
BaseType_t xWaitConditionMet, xAlreadyYielded;
|
||||
BaseType_t xTimeoutOccurred = pdFALSE;
|
||||
|
||||
/* Check the user is not attempting to wait on the bits used by the kernel
|
||||
itself, and that at least one bit is being requested. */
|
||||
configASSERT( xEventGroup );
|
||||
configASSERT( ( uxBitsToWaitFor & eventEVENT_BITS_CONTROL_BYTES ) == 0 );
|
||||
configASSERT( uxBitsToWaitFor != 0 );
|
||||
#if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) )
|
||||
{
|
||||
configASSERT( !( ( xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED ) && ( xTicksToWait != 0 ) ) );
|
||||
}
|
||||
#endif
|
||||
|
||||
vTaskSuspendAll();
|
||||
{
|
||||
const EventBits_t uxCurrentEventBits = pxEventBits->uxEventBits;
|
||||
|
||||
/* Check to see if the wait condition is already met or not. */
|
||||
xWaitConditionMet = prvTestWaitCondition( uxCurrentEventBits, uxBitsToWaitFor, xWaitForAllBits );
|
||||
|
||||
if( xWaitConditionMet != pdFALSE )
|
||||
{
|
||||
/* The wait condition has already been met so there is no need to
|
||||
block. */
|
||||
uxReturn = uxCurrentEventBits;
|
||||
xTicksToWait = ( TickType_t ) 0;
|
||||
|
||||
/* Clear the wait bits if requested to do so. */
|
||||
if( xClearOnExit != pdFALSE )
|
||||
{
|
||||
pxEventBits->uxEventBits &= ~uxBitsToWaitFor;
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
}
|
||||
else if( xTicksToWait == ( TickType_t ) 0 )
|
||||
{
|
||||
/* The wait condition has not been met, but no block time was
|
||||
specified, so just return the current value. */
|
||||
uxReturn = uxCurrentEventBits;
|
||||
xTimeoutOccurred = pdTRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* The task is going to block to wait for its required bits to be
|
||||
set. uxControlBits are used to remember the specified behaviour of
|
||||
this call to xEventGroupWaitBits() - for use when the event bits
|
||||
unblock the task. */
|
||||
if( xClearOnExit != pdFALSE )
|
||||
{
|
||||
uxControlBits |= eventCLEAR_EVENTS_ON_EXIT_BIT;
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
|
||||
if( xWaitForAllBits != pdFALSE )
|
||||
{
|
||||
uxControlBits |= eventWAIT_FOR_ALL_BITS;
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
|
||||
/* Store the bits that the calling task is waiting for in the
|
||||
task's event list item so the kernel knows when a match is
|
||||
found. Then enter the blocked state. */
|
||||
vTaskPlaceOnUnorderedEventList( &( pxEventBits->xTasksWaitingForBits ), ( uxBitsToWaitFor | uxControlBits ), xTicksToWait );
|
||||
|
||||
/* This is obsolete as it will get set after the task unblocks, but
|
||||
some compilers mistakenly generate a warning about the variable
|
||||
being returned without being set if it is not done. */
|
||||
uxReturn = 0;
|
||||
|
||||
traceEVENT_GROUP_WAIT_BITS_BLOCK( xEventGroup, uxBitsToWaitFor );
|
||||
}
|
||||
}
|
||||
xAlreadyYielded = xTaskResumeAll();
|
||||
|
||||
if( xTicksToWait != ( TickType_t ) 0 )
|
||||
{
|
||||
if( xAlreadyYielded == pdFALSE )
|
||||
{
|
||||
portYIELD_WITHIN_API();
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
|
||||
/* The task blocked to wait for its required bits to be set - at this
|
||||
point either the required bits were set or the block time expired. If
|
||||
the required bits were set they will have been stored in the task's
|
||||
event list item, and they should now be retrieved then cleared. */
|
||||
uxReturn = uxTaskResetEventItemValue();
|
||||
|
||||
if( ( uxReturn & eventUNBLOCKED_DUE_TO_BIT_SET ) == ( EventBits_t ) 0 )
|
||||
{
|
||||
taskENTER_CRITICAL();
|
||||
{
|
||||
/* The task timed out, just return the current event bit value. */
|
||||
uxReturn = pxEventBits->uxEventBits;
|
||||
|
||||
/* It is possible that the event bits were updated between this
|
||||
task leaving the Blocked state and running again. */
|
||||
if( prvTestWaitCondition( uxReturn, uxBitsToWaitFor, xWaitForAllBits ) != pdFALSE )
|
||||
{
|
||||
if( xClearOnExit != pdFALSE )
|
||||
{
|
||||
pxEventBits->uxEventBits &= ~uxBitsToWaitFor;
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
xTimeoutOccurred = pdTRUE;
|
||||
}
|
||||
taskEXIT_CRITICAL();
|
||||
}
|
||||
else
|
||||
{
|
||||
/* The task unblocked because the bits were set. */
|
||||
}
|
||||
|
||||
/* The task blocked so control bits may have been set. */
|
||||
uxReturn &= ~eventEVENT_BITS_CONTROL_BYTES;
|
||||
}
|
||||
traceEVENT_GROUP_WAIT_BITS_END( xEventGroup, uxBitsToWaitFor, xTimeoutOccurred );
|
||||
|
||||
/* Prevent compiler warnings when trace macros are not used. */
|
||||
( void ) xTimeoutOccurred;
|
||||
|
||||
return uxReturn;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
EventBits_t xEventGroupClearBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToClear )
|
||||
{
|
||||
EventGroup_t *pxEventBits = ( EventGroup_t * ) xEventGroup;
|
||||
EventBits_t uxReturn;
|
||||
|
||||
/* Check the user is not attempting to clear the bits used by the kernel
|
||||
itself. */
|
||||
configASSERT( xEventGroup );
|
||||
configASSERT( ( uxBitsToClear & eventEVENT_BITS_CONTROL_BYTES ) == 0 );
|
||||
|
||||
taskENTER_CRITICAL();
|
||||
{
|
||||
traceEVENT_GROUP_CLEAR_BITS( xEventGroup, uxBitsToClear );
|
||||
|
||||
/* The value returned is the event group value prior to the bits being
|
||||
cleared. */
|
||||
uxReturn = pxEventBits->uxEventBits;
|
||||
|
||||
/* Clear the bits. */
|
||||
pxEventBits->uxEventBits &= ~uxBitsToClear;
|
||||
}
|
||||
taskEXIT_CRITICAL();
|
||||
|
||||
return uxReturn;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if ( ( configUSE_TRACE_FACILITY == 1 ) && ( INCLUDE_xTimerPendFunctionCall == 1 ) && ( configUSE_TIMERS == 1 ) )
|
||||
|
||||
BaseType_t xEventGroupClearBitsFromISR( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToClear )
|
||||
{
|
||||
BaseType_t xReturn;
|
||||
|
||||
traceEVENT_GROUP_CLEAR_BITS_FROM_ISR( xEventGroup, uxBitsToClear );
|
||||
xReturn = xTimerPendFunctionCallFromISR( vEventGroupClearBitsCallback, ( void * ) xEventGroup, ( uint32_t ) uxBitsToClear, NULL );
|
||||
|
||||
return xReturn;
|
||||
}
|
||||
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
EventBits_t xEventGroupGetBitsFromISR( EventGroupHandle_t xEventGroup )
|
||||
{
|
||||
UBaseType_t uxSavedInterruptStatus;
|
||||
EventGroup_t *pxEventBits = ( EventGroup_t * ) xEventGroup;
|
||||
EventBits_t uxReturn;
|
||||
|
||||
uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
|
||||
{
|
||||
uxReturn = pxEventBits->uxEventBits;
|
||||
}
|
||||
portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );
|
||||
|
||||
return uxReturn;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
EventBits_t xEventGroupSetBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet )
|
||||
{
|
||||
ListItem_t *pxListItem, *pxNext;
|
||||
ListItem_t const *pxListEnd;
|
||||
List_t *pxList;
|
||||
EventBits_t uxBitsToClear = 0, uxBitsWaitedFor, uxControlBits;
|
||||
EventGroup_t *pxEventBits = ( EventGroup_t * ) xEventGroup;
|
||||
BaseType_t xMatchFound = pdFALSE;
|
||||
|
||||
/* Check the user is not attempting to set the bits used by the kernel
|
||||
itself. */
|
||||
configASSERT( xEventGroup );
|
||||
configASSERT( ( uxBitsToSet & eventEVENT_BITS_CONTROL_BYTES ) == 0 );
|
||||
|
||||
pxList = &( pxEventBits->xTasksWaitingForBits );
|
||||
pxListEnd = listGET_END_MARKER( pxList ); /*lint !e826 !e740 The mini list structure is used as the list end to save RAM. This is checked and valid. */
|
||||
vTaskSuspendAll();
|
||||
{
|
||||
traceEVENT_GROUP_SET_BITS( xEventGroup, uxBitsToSet );
|
||||
|
||||
pxListItem = listGET_HEAD_ENTRY( pxList );
|
||||
|
||||
/* Set the bits. */
|
||||
pxEventBits->uxEventBits |= uxBitsToSet;
|
||||
|
||||
/* See if the new bit value should unblock any tasks. */
|
||||
while( pxListItem != pxListEnd )
|
||||
{
|
||||
pxNext = listGET_NEXT( pxListItem );
|
||||
uxBitsWaitedFor = listGET_LIST_ITEM_VALUE( pxListItem );
|
||||
xMatchFound = pdFALSE;
|
||||
|
||||
/* Split the bits waited for from the control bits. */
|
||||
uxControlBits = uxBitsWaitedFor & eventEVENT_BITS_CONTROL_BYTES;
|
||||
uxBitsWaitedFor &= ~eventEVENT_BITS_CONTROL_BYTES;
|
||||
|
||||
if( ( uxControlBits & eventWAIT_FOR_ALL_BITS ) == ( EventBits_t ) 0 )
|
||||
{
|
||||
/* Just looking for single bit being set. */
|
||||
if( ( uxBitsWaitedFor & pxEventBits->uxEventBits ) != ( EventBits_t ) 0 )
|
||||
{
|
||||
xMatchFound = pdTRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
}
|
||||
else if( ( uxBitsWaitedFor & pxEventBits->uxEventBits ) == uxBitsWaitedFor )
|
||||
{
|
||||
/* All bits are set. */
|
||||
xMatchFound = pdTRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Need all bits to be set, but not all the bits were set. */
|
||||
}
|
||||
|
||||
if( xMatchFound != pdFALSE )
|
||||
{
|
||||
/* The bits match. Should the bits be cleared on exit? */
|
||||
if( ( uxControlBits & eventCLEAR_EVENTS_ON_EXIT_BIT ) != ( EventBits_t ) 0 )
|
||||
{
|
||||
uxBitsToClear |= uxBitsWaitedFor;
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
|
||||
/* Store the actual event flag value in the task's event list
|
||||
item before removing the task from the event list. The
|
||||
eventUNBLOCKED_DUE_TO_BIT_SET bit is set so the task knows
|
||||
that is was unblocked due to its required bits matching, rather
|
||||
than because it timed out. */
|
||||
vTaskRemoveFromUnorderedEventList( pxListItem, pxEventBits->uxEventBits | eventUNBLOCKED_DUE_TO_BIT_SET );
|
||||
}
|
||||
|
||||
/* Move onto the next list item. Note pxListItem->pxNext is not
|
||||
used here as the list item may have been removed from the event list
|
||||
and inserted into the ready/pending reading list. */
|
||||
pxListItem = pxNext;
|
||||
}
|
||||
|
||||
/* Clear any bits that matched when the eventCLEAR_EVENTS_ON_EXIT_BIT
|
||||
bit was set in the control word. */
|
||||
pxEventBits->uxEventBits &= ~uxBitsToClear;
|
||||
}
|
||||
( void ) xTaskResumeAll();
|
||||
|
||||
return pxEventBits->uxEventBits;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vEventGroupDelete( EventGroupHandle_t xEventGroup )
|
||||
{
|
||||
EventGroup_t *pxEventBits = ( EventGroup_t * ) xEventGroup;
|
||||
const List_t *pxTasksWaitingForBits = &( pxEventBits->xTasksWaitingForBits );
|
||||
|
||||
vTaskSuspendAll();
|
||||
{
|
||||
traceEVENT_GROUP_DELETE( xEventGroup );
|
||||
|
||||
while( listCURRENT_LIST_LENGTH( pxTasksWaitingForBits ) > ( UBaseType_t ) 0 )
|
||||
{
|
||||
/* Unblock the task, returning 0 as the event list is being deleted
|
||||
and cannot therefore have any bits set. */
|
||||
configASSERT( pxTasksWaitingForBits->xListEnd.pxNext != ( const ListItem_t * ) &( pxTasksWaitingForBits->xListEnd ) );
|
||||
vTaskRemoveFromUnorderedEventList( pxTasksWaitingForBits->xListEnd.pxNext, eventUNBLOCKED_DUE_TO_BIT_SET );
|
||||
}
|
||||
|
||||
#if( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 0 ) )
|
||||
{
|
||||
/* The event group can only have been allocated dynamically - free
|
||||
it again. */
|
||||
vPortFree( pxEventBits );
|
||||
}
|
||||
#elif( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) )
|
||||
{
|
||||
/* The event group could have been allocated statically or
|
||||
dynamically, so check before attempting to free the memory. */
|
||||
if( pxEventBits->ucStaticallyAllocated == ( uint8_t ) pdFALSE )
|
||||
{
|
||||
vPortFree( pxEventBits );
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
}
|
||||
#endif /* configSUPPORT_DYNAMIC_ALLOCATION */
|
||||
}
|
||||
( void ) xTaskResumeAll();
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* For internal use only - execute a 'set bits' command that was pended from
|
||||
an interrupt. */
|
||||
void vEventGroupSetBitsCallback( void *pvEventGroup, const uint32_t ulBitsToSet )
|
||||
{
|
||||
( void ) xEventGroupSetBits( pvEventGroup, ( EventBits_t ) ulBitsToSet );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* For internal use only - execute a 'clear bits' command that was pended from
|
||||
an interrupt. */
|
||||
void vEventGroupClearBitsCallback( void *pvEventGroup, const uint32_t ulBitsToClear )
|
||||
{
|
||||
( void ) xEventGroupClearBits( pvEventGroup, ( EventBits_t ) ulBitsToClear );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static BaseType_t prvTestWaitCondition( const EventBits_t uxCurrentEventBits, const EventBits_t uxBitsToWaitFor, const BaseType_t xWaitForAllBits )
|
||||
{
|
||||
BaseType_t xWaitConditionMet = pdFALSE;
|
||||
|
||||
if( xWaitForAllBits == pdFALSE )
|
||||
{
|
||||
/* Task only has to wait for one bit within uxBitsToWaitFor to be
|
||||
set. Is one already set? */
|
||||
if( ( uxCurrentEventBits & uxBitsToWaitFor ) != ( EventBits_t ) 0 )
|
||||
{
|
||||
xWaitConditionMet = pdTRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Task has to wait for all the bits in uxBitsToWaitFor to be set.
|
||||
Are they set already? */
|
||||
if( ( uxCurrentEventBits & uxBitsToWaitFor ) == uxBitsToWaitFor )
|
||||
{
|
||||
xWaitConditionMet = pdTRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
}
|
||||
|
||||
return xWaitConditionMet;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if ( ( configUSE_TRACE_FACILITY == 1 ) && ( INCLUDE_xTimerPendFunctionCall == 1 ) && ( configUSE_TIMERS == 1 ) )
|
||||
|
||||
BaseType_t xEventGroupSetBitsFromISR( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet, BaseType_t *pxHigherPriorityTaskWoken )
|
||||
{
|
||||
BaseType_t xReturn;
|
||||
|
||||
traceEVENT_GROUP_SET_BITS_FROM_ISR( xEventGroup, uxBitsToSet );
|
||||
xReturn = xTimerPendFunctionCallFromISR( vEventGroupSetBitsCallback, ( void * ) xEventGroup, ( uint32_t ) uxBitsToSet, pxHigherPriorityTaskWoken );
|
||||
|
||||
return xReturn;
|
||||
}
|
||||
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if (configUSE_TRACE_FACILITY == 1)
|
||||
|
||||
UBaseType_t uxEventGroupGetNumber( void* xEventGroup )
|
||||
{
|
||||
UBaseType_t xReturn;
|
||||
EventGroup_t *pxEventBits = ( EventGroup_t * ) xEventGroup;
|
||||
|
||||
if( xEventGroup == NULL )
|
||||
{
|
||||
xReturn = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
xReturn = pxEventBits->uxEventGroupNumber;
|
||||
}
|
||||
|
||||
return xReturn;
|
||||
}
|
||||
|
||||
#endif /* configUSE_TRACE_FACILITY */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if ( configUSE_TRACE_FACILITY == 1 )
|
||||
|
||||
void vEventGroupSetNumber( void * xEventGroup, UBaseType_t uxEventGroupNumber )
|
||||
{
|
||||
( ( EventGroup_t * ) xEventGroup )->uxEventGroupNumber = uxEventGroupNumber;
|
||||
}
|
||||
|
||||
#endif /* configUSE_TRACE_FACILITY */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,147 +0,0 @@
|
||||
/* Copyright 2018 Canaan Inc.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* http://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.
|
||||
*/
|
||||
/*
|
||||
* FreeRTOS Kernel V10.0.1
|
||||
* Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* http://www.FreeRTOS.org
|
||||
* http://aws.amazon.com/freertos
|
||||
*
|
||||
* 1 tab == 4 spaces!
|
||||
*/
|
||||
|
||||
#ifndef STACK_MACROS_H
|
||||
#define STACK_MACROS_H
|
||||
|
||||
#ifndef _MSC_VER /* Visual Studio doesn't support #warning. */
|
||||
#warning The name of this file has changed to stack_macros.h. Please update your code accordingly. This source file (which has the original name) will be removed in future released.
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Call the stack overflow hook function if the stack of the task being swapped
|
||||
* out is currently overflowed, or looks like it might have overflowed in the
|
||||
* past.
|
||||
*
|
||||
* Setting configCHECK_FOR_STACK_OVERFLOW to 1 will cause the macro to check
|
||||
* the current stack state only - comparing the current top of stack value to
|
||||
* the stack limit. Setting configCHECK_FOR_STACK_OVERFLOW to greater than 1
|
||||
* will also cause the last few stack bytes to be checked to ensure the value
|
||||
* to which the bytes were set when the task was created have not been
|
||||
* overwritten. Note this second test does not guarantee that an overflowed
|
||||
* stack will always be recognised.
|
||||
*/
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if( ( configCHECK_FOR_STACK_OVERFLOW == 1 ) && ( portSTACK_GROWTH < 0 ) )
|
||||
|
||||
/* Only the current stack state is to be checked. */
|
||||
#define taskCHECK_FOR_STACK_OVERFLOW() \
|
||||
{ \
|
||||
/* Is the currently saved stack pointer within the stack limit? */ \
|
||||
if( pxCurrentTCB->pxTopOfStack <= pxCurrentTCB->pxStack ) \
|
||||
{ \
|
||||
vApplicationStackOverflowHook( ( TaskHandle_t ) pxCurrentTCB, pxCurrentTCB->pcTaskName ); \
|
||||
} \
|
||||
}
|
||||
|
||||
#endif /* configCHECK_FOR_STACK_OVERFLOW == 1 */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if( ( configCHECK_FOR_STACK_OVERFLOW == 1 ) && ( portSTACK_GROWTH > 0 ) )
|
||||
|
||||
/* Only the current stack state is to be checked. */
|
||||
#define taskCHECK_FOR_STACK_OVERFLOW() \
|
||||
{ \
|
||||
\
|
||||
/* Is the currently saved stack pointer within the stack limit? */ \
|
||||
if( pxCurrentTCB->pxTopOfStack >= pxCurrentTCB->pxEndOfStack ) \
|
||||
{ \
|
||||
vApplicationStackOverflowHook( ( TaskHandle_t ) pxCurrentTCB, pxCurrentTCB->pcTaskName ); \
|
||||
} \
|
||||
}
|
||||
|
||||
#endif /* configCHECK_FOR_STACK_OVERFLOW == 1 */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if( ( configCHECK_FOR_STACK_OVERFLOW > 1 ) && ( portSTACK_GROWTH < 0 ) )
|
||||
|
||||
#define taskCHECK_FOR_STACK_OVERFLOW() \
|
||||
{ \
|
||||
const uint32_t * const pulStack = ( uint32_t * ) pxCurrentTCB->pxStack; \
|
||||
const uint32_t ulCheckValue = ( uint32_t ) 0xa5a5a5a5; \
|
||||
\
|
||||
if( ( pulStack[ 0 ] != ulCheckValue ) || \
|
||||
( pulStack[ 1 ] != ulCheckValue ) || \
|
||||
( pulStack[ 2 ] != ulCheckValue ) || \
|
||||
( pulStack[ 3 ] != ulCheckValue ) ) \
|
||||
{ \
|
||||
vApplicationStackOverflowHook( ( TaskHandle_t ) pxCurrentTCB, pxCurrentTCB->pcTaskName ); \
|
||||
} \
|
||||
}
|
||||
|
||||
#endif /* #if( configCHECK_FOR_STACK_OVERFLOW > 1 ) */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if( ( configCHECK_FOR_STACK_OVERFLOW > 1 ) && ( portSTACK_GROWTH > 0 ) )
|
||||
|
||||
#define taskCHECK_FOR_STACK_OVERFLOW() \
|
||||
{ \
|
||||
int8_t *pcEndOfStack = ( int8_t * ) pxCurrentTCB->pxEndOfStack; \
|
||||
static const uint8_t ucExpectedStackBytes[] = { tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \
|
||||
tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \
|
||||
tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \
|
||||
tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \
|
||||
tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE }; \
|
||||
\
|
||||
\
|
||||
pcEndOfStack -= sizeof( ucExpectedStackBytes ); \
|
||||
\
|
||||
/* Has the extremity of the task stack ever been written over? */ \
|
||||
if( memcmp( ( void * ) pcEndOfStack, ( void * ) ucExpectedStackBytes, sizeof( ucExpectedStackBytes ) ) != 0 ) \
|
||||
{ \
|
||||
vApplicationStackOverflowHook( ( TaskHandle_t ) pxCurrentTCB, pxCurrentTCB->pcTaskName ); \
|
||||
} \
|
||||
}
|
||||
|
||||
#endif /* #if( configCHECK_FOR_STACK_OVERFLOW > 1 ) */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Remove stack overflow macro if not being used. */
|
||||
#ifndef taskCHECK_FOR_STACK_OVERFLOW
|
||||
#define taskCHECK_FOR_STACK_OVERFLOW()
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#endif /* STACK_MACROS_H */
|
||||
|
||||
@@ -1,43 +0,0 @@
|
||||
/* Copyright 2018 Canaan Inc.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* http://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.
|
||||
*/
|
||||
//
|
||||
// Core Synchronization
|
||||
|
||||
#ifndef CORE_SYNC_H
|
||||
#define CORE_SYNC_H
|
||||
|
||||
#include "FreeRTOS.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
typedef enum
|
||||
{
|
||||
CORE_SYNC_NONE,
|
||||
CORE_SYNC_ADD_TCB
|
||||
} core_sync_event_t;
|
||||
|
||||
void core_sync_request_context_switch(uint64_t core_id);
|
||||
void core_sync_complete_context_switch(uint64_t core_id);
|
||||
void core_sync_complete(uint64_t core_id);
|
||||
int core_sync_is_in_progress(uint64_t core_id);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* CORE_SYNC_H */
|
||||
@@ -1,734 +0,0 @@
|
||||
/* Copyright 2018 Canaan Inc.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* http://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.
|
||||
*/
|
||||
/*
|
||||
* FreeRTOS Kernel V10.0.1
|
||||
* Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* http://www.FreeRTOS.org
|
||||
* http://aws.amazon.com/freertos
|
||||
*
|
||||
* 1 tab == 4 spaces!
|
||||
*/
|
||||
|
||||
#ifndef CO_ROUTINE_H
|
||||
#define CO_ROUTINE_H
|
||||
|
||||
#ifndef INC_FREERTOS_H
|
||||
#error "include FreeRTOS.h must appear in source files before include croutine.h"
|
||||
#endif
|
||||
|
||||
#include "list.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Used to hide the implementation of the co-routine control block. The
|
||||
control block structure however has to be included in the header due to
|
||||
the macro implementation of the co-routine functionality. */
|
||||
typedef void * CoRoutineHandle_t;
|
||||
|
||||
/* Defines the prototype to which co-routine functions must conform. */
|
||||
typedef void (*crCOROUTINE_CODE)( CoRoutineHandle_t, UBaseType_t );
|
||||
|
||||
typedef struct corCoRoutineControlBlock
|
||||
{
|
||||
crCOROUTINE_CODE pxCoRoutineFunction;
|
||||
ListItem_t xGenericListItem; /*< List item used to place the CRCB in ready and blocked queues. */
|
||||
ListItem_t xEventListItem; /*< List item used to place the CRCB in event lists. */
|
||||
UBaseType_t uxPriority; /*< The priority of the co-routine in relation to other co-routines. */
|
||||
UBaseType_t uxIndex; /*< Used to distinguish between co-routines when multiple co-routines use the same co-routine function. */
|
||||
uint16_t uxState; /*< Used internally by the co-routine implementation. */
|
||||
} CRCB_t; /* Co-routine control block. Note must be identical in size down to uxPriority with TCB_t. */
|
||||
|
||||
/**
|
||||
* croutine. h
|
||||
*<pre>
|
||||
BaseType_t xCoRoutineCreate(
|
||||
crCOROUTINE_CODE pxCoRoutineCode,
|
||||
UBaseType_t uxPriority,
|
||||
UBaseType_t uxIndex
|
||||
);</pre>
|
||||
*
|
||||
* Create a new co-routine and add it to the list of co-routines that are
|
||||
* ready to run.
|
||||
*
|
||||
* @param pxCoRoutineCode Pointer to the co-routine function. Co-routine
|
||||
* functions require special syntax - see the co-routine section of the WEB
|
||||
* documentation for more information.
|
||||
*
|
||||
* @param uxPriority The priority with respect to other co-routines at which
|
||||
* the co-routine will run.
|
||||
*
|
||||
* @param uxIndex Used to distinguish between different co-routines that
|
||||
* execute the same function. See the example below and the co-routine section
|
||||
* of the WEB documentation for further information.
|
||||
*
|
||||
* @return pdPASS if the co-routine was successfully created and added to a ready
|
||||
* list, otherwise an error code defined with ProjDefs.h.
|
||||
*
|
||||
* Example usage:
|
||||
<pre>
|
||||
// Co-routine to be created.
|
||||
void vFlashCoRoutine( CoRoutineHandle_t xHandle, UBaseType_t uxIndex )
|
||||
{
|
||||
// Variables in co-routines must be declared static if they must maintain value across a blocking call.
|
||||
// This may not be necessary for const variables.
|
||||
static const char cLedToFlash[ 2 ] = { 5, 6 };
|
||||
static const TickType_t uxFlashRates[ 2 ] = { 200, 400 };
|
||||
|
||||
// Must start every co-routine with a call to crSTART();
|
||||
crSTART( xHandle );
|
||||
|
||||
for( ;; )
|
||||
{
|
||||
// This co-routine just delays for a fixed period, then toggles
|
||||
// an LED. Two co-routines are created using this function, so
|
||||
// the uxIndex parameter is used to tell the co-routine which
|
||||
// LED to flash and how int32_t to delay. This assumes xQueue has
|
||||
// already been created.
|
||||
vParTestToggleLED( cLedToFlash[ uxIndex ] );
|
||||
crDELAY( xHandle, uxFlashRates[ uxIndex ] );
|
||||
}
|
||||
|
||||
// Must end every co-routine with a call to crEND();
|
||||
crEND();
|
||||
}
|
||||
|
||||
// Function that creates two co-routines.
|
||||
void vOtherFunction( void )
|
||||
{
|
||||
uint8_t ucParameterToPass;
|
||||
TaskHandle_t xHandle;
|
||||
|
||||
// Create two co-routines at priority 0. The first is given index 0
|
||||
// so (from the code above) toggles LED 5 every 200 ticks. The second
|
||||
// is given index 1 so toggles LED 6 every 400 ticks.
|
||||
for( uxIndex = 0; uxIndex < 2; uxIndex++ )
|
||||
{
|
||||
xCoRoutineCreate( vFlashCoRoutine, 0, uxIndex );
|
||||
}
|
||||
}
|
||||
</pre>
|
||||
* \defgroup xCoRoutineCreate xCoRoutineCreate
|
||||
* \ingroup Tasks
|
||||
*/
|
||||
BaseType_t xCoRoutineCreate( crCOROUTINE_CODE pxCoRoutineCode, UBaseType_t uxPriority, UBaseType_t uxIndex );
|
||||
|
||||
|
||||
/**
|
||||
* croutine. h
|
||||
*<pre>
|
||||
void vCoRoutineSchedule( void );</pre>
|
||||
*
|
||||
* Run a co-routine.
|
||||
*
|
||||
* vCoRoutineSchedule() executes the highest priority co-routine that is able
|
||||
* to run. The co-routine will execute until it either blocks, yields or is
|
||||
* preempted by a task. Co-routines execute cooperatively so one
|
||||
* co-routine cannot be preempted by another, but can be preempted by a task.
|
||||
*
|
||||
* If an application comprises of both tasks and co-routines then
|
||||
* vCoRoutineSchedule should be called from the idle task (in an idle task
|
||||
* hook).
|
||||
*
|
||||
* Example usage:
|
||||
<pre>
|
||||
// This idle task hook will schedule a co-routine each time it is called.
|
||||
// The rest of the idle task will execute between co-routine calls.
|
||||
void vApplicationIdleHook( void )
|
||||
{
|
||||
vCoRoutineSchedule();
|
||||
}
|
||||
|
||||
// Alternatively, if you do not require any other part of the idle task to
|
||||
// execute, the idle task hook can call vCoRoutineScheduler() within an
|
||||
// infinite loop.
|
||||
void vApplicationIdleHook( void )
|
||||
{
|
||||
for( ;; )
|
||||
{
|
||||
vCoRoutineSchedule();
|
||||
}
|
||||
}
|
||||
</pre>
|
||||
* \defgroup vCoRoutineSchedule vCoRoutineSchedule
|
||||
* \ingroup Tasks
|
||||
*/
|
||||
void vCoRoutineSchedule( void );
|
||||
|
||||
/**
|
||||
* croutine. h
|
||||
* <pre>
|
||||
crSTART( CoRoutineHandle_t xHandle );</pre>
|
||||
*
|
||||
* This macro MUST always be called at the start of a co-routine function.
|
||||
*
|
||||
* Example usage:
|
||||
<pre>
|
||||
// Co-routine to be created.
|
||||
void vACoRoutine( CoRoutineHandle_t xHandle, UBaseType_t uxIndex )
|
||||
{
|
||||
// Variables in co-routines must be declared static if they must maintain value across a blocking call.
|
||||
static int32_t ulAVariable;
|
||||
|
||||
// Must start every co-routine with a call to crSTART();
|
||||
crSTART( xHandle );
|
||||
|
||||
for( ;; )
|
||||
{
|
||||
// Co-routine functionality goes here.
|
||||
}
|
||||
|
||||
// Must end every co-routine with a call to crEND();
|
||||
crEND();
|
||||
}</pre>
|
||||
* \defgroup crSTART crSTART
|
||||
* \ingroup Tasks
|
||||
*/
|
||||
#define crSTART( pxCRCB ) switch( ( ( CRCB_t * )( pxCRCB ) )->uxState ) { case 0:
|
||||
|
||||
/**
|
||||
* croutine. h
|
||||
* <pre>
|
||||
crEND();</pre>
|
||||
*
|
||||
* This macro MUST always be called at the end of a co-routine function.
|
||||
*
|
||||
* Example usage:
|
||||
<pre>
|
||||
// Co-routine to be created.
|
||||
void vACoRoutine( CoRoutineHandle_t xHandle, UBaseType_t uxIndex )
|
||||
{
|
||||
// Variables in co-routines must be declared static if they must maintain value across a blocking call.
|
||||
static int32_t ulAVariable;
|
||||
|
||||
// Must start every co-routine with a call to crSTART();
|
||||
crSTART( xHandle );
|
||||
|
||||
for( ;; )
|
||||
{
|
||||
// Co-routine functionality goes here.
|
||||
}
|
||||
|
||||
// Must end every co-routine with a call to crEND();
|
||||
crEND();
|
||||
}</pre>
|
||||
* \defgroup crSTART crSTART
|
||||
* \ingroup Tasks
|
||||
*/
|
||||
#define crEND() }
|
||||
|
||||
/*
|
||||
* These macros are intended for internal use by the co-routine implementation
|
||||
* only. The macros should not be used directly by application writers.
|
||||
*/
|
||||
#define crSET_STATE0( xHandle ) ( ( CRCB_t * )( xHandle ) )->uxState = (__LINE__ * 2); return; case (__LINE__ * 2):
|
||||
#define crSET_STATE1( xHandle ) ( ( CRCB_t * )( xHandle ) )->uxState = ((__LINE__ * 2)+1); return; case ((__LINE__ * 2)+1):
|
||||
|
||||
/**
|
||||
* croutine. h
|
||||
*<pre>
|
||||
crDELAY( CoRoutineHandle_t xHandle, TickType_t xTicksToDelay );</pre>
|
||||
*
|
||||
* Delay a co-routine for a fixed period of time.
|
||||
*
|
||||
* crDELAY can only be called from the co-routine function itself - not
|
||||
* from within a function called by the co-routine function. This is because
|
||||
* co-routines do not maintain their own stack.
|
||||
*
|
||||
* @param xHandle The handle of the co-routine to delay. This is the xHandle
|
||||
* parameter of the co-routine function.
|
||||
*
|
||||
* @param xTickToDelay The number of ticks that the co-routine should delay
|
||||
* for. The actual amount of time this equates to is defined by
|
||||
* configTICK_RATE_HZ (set in FreeRTOSConfig.h). The constant portTICK_PERIOD_MS
|
||||
* can be used to convert ticks to milliseconds.
|
||||
*
|
||||
* Example usage:
|
||||
<pre>
|
||||
// Co-routine to be created.
|
||||
void vACoRoutine( CoRoutineHandle_t xHandle, UBaseType_t uxIndex )
|
||||
{
|
||||
// Variables in co-routines must be declared static if they must maintain value across a blocking call.
|
||||
// This may not be necessary for const variables.
|
||||
// We are to delay for 200ms.
|
||||
static const xTickType xDelayTime = 200 / portTICK_PERIOD_MS;
|
||||
|
||||
// Must start every co-routine with a call to crSTART();
|
||||
crSTART( xHandle );
|
||||
|
||||
for( ;; )
|
||||
{
|
||||
// Delay for 200ms.
|
||||
crDELAY( xHandle, xDelayTime );
|
||||
|
||||
// Do something here.
|
||||
}
|
||||
|
||||
// Must end every co-routine with a call to crEND();
|
||||
crEND();
|
||||
}</pre>
|
||||
* \defgroup crDELAY crDELAY
|
||||
* \ingroup Tasks
|
||||
*/
|
||||
#define crDELAY( xHandle, xTicksToDelay ) \
|
||||
if( ( xTicksToDelay ) > 0 ) \
|
||||
{ \
|
||||
vCoRoutineAddToDelayedList( ( xTicksToDelay ), NULL ); \
|
||||
} \
|
||||
crSET_STATE0( ( xHandle ) );
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
crQUEUE_SEND(
|
||||
CoRoutineHandle_t xHandle,
|
||||
QueueHandle_t pxQueue,
|
||||
void *pvItemToQueue,
|
||||
TickType_t xTicksToWait,
|
||||
BaseType_t *pxResult
|
||||
)</pre>
|
||||
*
|
||||
* The macro's crQUEUE_SEND() and crQUEUE_RECEIVE() are the co-routine
|
||||
* equivalent to the xQueueSend() and xQueueReceive() functions used by tasks.
|
||||
*
|
||||
* crQUEUE_SEND and crQUEUE_RECEIVE can only be used from a co-routine whereas
|
||||
* xQueueSend() and xQueueReceive() can only be used from tasks.
|
||||
*
|
||||
* crQUEUE_SEND can only be called from the co-routine function itself - not
|
||||
* from within a function called by the co-routine function. This is because
|
||||
* co-routines do not maintain their own stack.
|
||||
*
|
||||
* See the co-routine section of the WEB documentation for information on
|
||||
* passing data between tasks and co-routines and between ISR's and
|
||||
* co-routines.
|
||||
*
|
||||
* @param xHandle The handle of the calling co-routine. This is the xHandle
|
||||
* parameter of the co-routine function.
|
||||
*
|
||||
* @param pxQueue The handle of the queue on which the data will be posted.
|
||||
* The handle is obtained as the return value when the queue is created using
|
||||
* the xQueueCreate() API function.
|
||||
*
|
||||
* @param pvItemToQueue A pointer to the data being posted onto the queue.
|
||||
* The number of bytes of each queued item is specified when the queue is
|
||||
* created. This number of bytes is copied from pvItemToQueue into the queue
|
||||
* itself.
|
||||
*
|
||||
* @param xTickToDelay The number of ticks that the co-routine should block
|
||||
* to wait for space to become available on the queue, should space not be
|
||||
* available immediately. The actual amount of time this equates to is defined
|
||||
* by configTICK_RATE_HZ (set in FreeRTOSConfig.h). The constant
|
||||
* portTICK_PERIOD_MS can be used to convert ticks to milliseconds (see example
|
||||
* below).
|
||||
*
|
||||
* @param pxResult The variable pointed to by pxResult will be set to pdPASS if
|
||||
* data was successfully posted onto the queue, otherwise it will be set to an
|
||||
* error defined within ProjDefs.h.
|
||||
*
|
||||
* Example usage:
|
||||
<pre>
|
||||
// Co-routine function that blocks for a fixed period then posts a number onto
|
||||
// a queue.
|
||||
static void prvCoRoutineFlashTask( CoRoutineHandle_t xHandle, UBaseType_t uxIndex )
|
||||
{
|
||||
// Variables in co-routines must be declared static if they must maintain value across a blocking call.
|
||||
static BaseType_t xNumberToPost = 0;
|
||||
static BaseType_t xResult;
|
||||
|
||||
// Co-routines must begin with a call to crSTART().
|
||||
crSTART( xHandle );
|
||||
|
||||
for( ;; )
|
||||
{
|
||||
// This assumes the queue has already been created.
|
||||
crQUEUE_SEND( xHandle, xCoRoutineQueue, &xNumberToPost, NO_DELAY, &xResult );
|
||||
|
||||
if( xResult != pdPASS )
|
||||
{
|
||||
// The message was not posted!
|
||||
}
|
||||
|
||||
// Increment the number to be posted onto the queue.
|
||||
xNumberToPost++;
|
||||
|
||||
// Delay for 100 ticks.
|
||||
crDELAY( xHandle, 100 );
|
||||
}
|
||||
|
||||
// Co-routines must end with a call to crEND().
|
||||
crEND();
|
||||
}</pre>
|
||||
* \defgroup crQUEUE_SEND crQUEUE_SEND
|
||||
* \ingroup Tasks
|
||||
*/
|
||||
#define crQUEUE_SEND( xHandle, pxQueue, pvItemToQueue, xTicksToWait, pxResult ) \
|
||||
{ \
|
||||
*( pxResult ) = xQueueCRSend( ( pxQueue) , ( pvItemToQueue) , ( xTicksToWait ) ); \
|
||||
if( *( pxResult ) == errQUEUE_BLOCKED ) \
|
||||
{ \
|
||||
crSET_STATE0( ( xHandle ) ); \
|
||||
*pxResult = xQueueCRSend( ( pxQueue ), ( pvItemToQueue ), 0 ); \
|
||||
} \
|
||||
if( *pxResult == errQUEUE_YIELD ) \
|
||||
{ \
|
||||
crSET_STATE1( ( xHandle ) ); \
|
||||
*pxResult = pdPASS; \
|
||||
} \
|
||||
}
|
||||
|
||||
/**
|
||||
* croutine. h
|
||||
* <pre>
|
||||
crQUEUE_RECEIVE(
|
||||
CoRoutineHandle_t xHandle,
|
||||
QueueHandle_t pxQueue,
|
||||
void *pvBuffer,
|
||||
TickType_t xTicksToWait,
|
||||
BaseType_t *pxResult
|
||||
)</pre>
|
||||
*
|
||||
* The macro's crQUEUE_SEND() and crQUEUE_RECEIVE() are the co-routine
|
||||
* equivalent to the xQueueSend() and xQueueReceive() functions used by tasks.
|
||||
*
|
||||
* crQUEUE_SEND and crQUEUE_RECEIVE can only be used from a co-routine whereas
|
||||
* xQueueSend() and xQueueReceive() can only be used from tasks.
|
||||
*
|
||||
* crQUEUE_RECEIVE can only be called from the co-routine function itself - not
|
||||
* from within a function called by the co-routine function. This is because
|
||||
* co-routines do not maintain their own stack.
|
||||
*
|
||||
* See the co-routine section of the WEB documentation for information on
|
||||
* passing data between tasks and co-routines and between ISR's and
|
||||
* co-routines.
|
||||
*
|
||||
* @param xHandle The handle of the calling co-routine. This is the xHandle
|
||||
* parameter of the co-routine function.
|
||||
*
|
||||
* @param pxQueue The handle of the queue from which the data will be received.
|
||||
* The handle is obtained as the return value when the queue is created using
|
||||
* the xQueueCreate() API function.
|
||||
*
|
||||
* @param pvBuffer The buffer into which the received item is to be copied.
|
||||
* The number of bytes of each queued item is specified when the queue is
|
||||
* created. This number of bytes is copied into pvBuffer.
|
||||
*
|
||||
* @param xTickToDelay The number of ticks that the co-routine should block
|
||||
* to wait for data to become available from the queue, should data not be
|
||||
* available immediately. The actual amount of time this equates to is defined
|
||||
* by configTICK_RATE_HZ (set in FreeRTOSConfig.h). The constant
|
||||
* portTICK_PERIOD_MS can be used to convert ticks to milliseconds (see the
|
||||
* crQUEUE_SEND example).
|
||||
*
|
||||
* @param pxResult The variable pointed to by pxResult will be set to pdPASS if
|
||||
* data was successfully retrieved from the queue, otherwise it will be set to
|
||||
* an error code as defined within ProjDefs.h.
|
||||
*
|
||||
* Example usage:
|
||||
<pre>
|
||||
// A co-routine receives the number of an LED to flash from a queue. It
|
||||
// blocks on the queue until the number is received.
|
||||
static void prvCoRoutineFlashWorkTask( CoRoutineHandle_t xHandle, UBaseType_t uxIndex )
|
||||
{
|
||||
// Variables in co-routines must be declared static if they must maintain value across a blocking call.
|
||||
static BaseType_t xResult;
|
||||
static UBaseType_t uxLEDToFlash;
|
||||
|
||||
// All co-routines must start with a call to crSTART().
|
||||
crSTART( xHandle );
|
||||
|
||||
for( ;; )
|
||||
{
|
||||
// Wait for data to become available on the queue.
|
||||
crQUEUE_RECEIVE( xHandle, xCoRoutineQueue, &uxLEDToFlash, portMAX_DELAY, &xResult );
|
||||
|
||||
if( xResult == pdPASS )
|
||||
{
|
||||
// We received the LED to flash - flash it!
|
||||
vParTestToggleLED( uxLEDToFlash );
|
||||
}
|
||||
}
|
||||
|
||||
crEND();
|
||||
}</pre>
|
||||
* \defgroup crQUEUE_RECEIVE crQUEUE_RECEIVE
|
||||
* \ingroup Tasks
|
||||
*/
|
||||
#define crQUEUE_RECEIVE( xHandle, pxQueue, pvBuffer, xTicksToWait, pxResult ) \
|
||||
{ \
|
||||
*( pxResult ) = xQueueCRReceive( ( pxQueue) , ( pvBuffer ), ( xTicksToWait ) ); \
|
||||
if( *( pxResult ) == errQUEUE_BLOCKED ) \
|
||||
{ \
|
||||
crSET_STATE0( ( xHandle ) ); \
|
||||
*( pxResult ) = xQueueCRReceive( ( pxQueue) , ( pvBuffer ), 0 ); \
|
||||
} \
|
||||
if( *( pxResult ) == errQUEUE_YIELD ) \
|
||||
{ \
|
||||
crSET_STATE1( ( xHandle ) ); \
|
||||
*( pxResult ) = pdPASS; \
|
||||
} \
|
||||
}
|
||||
|
||||
/**
|
||||
* croutine. h
|
||||
* <pre>
|
||||
crQUEUE_SEND_FROM_ISR(
|
||||
QueueHandle_t pxQueue,
|
||||
void *pvItemToQueue,
|
||||
BaseType_t xCoRoutinePreviouslyWoken
|
||||
)</pre>
|
||||
*
|
||||
* The macro's crQUEUE_SEND_FROM_ISR() and crQUEUE_RECEIVE_FROM_ISR() are the
|
||||
* co-routine equivalent to the xQueueSendFromISR() and xQueueReceiveFromISR()
|
||||
* functions used by tasks.
|
||||
*
|
||||
* crQUEUE_SEND_FROM_ISR() and crQUEUE_RECEIVE_FROM_ISR() can only be used to
|
||||
* pass data between a co-routine and and ISR, whereas xQueueSendFromISR() and
|
||||
* xQueueReceiveFromISR() can only be used to pass data between a task and and
|
||||
* ISR.
|
||||
*
|
||||
* crQUEUE_SEND_FROM_ISR can only be called from an ISR to send data to a queue
|
||||
* that is being used from within a co-routine.
|
||||
*
|
||||
* See the co-routine section of the WEB documentation for information on
|
||||
* passing data between tasks and co-routines and between ISR's and
|
||||
* co-routines.
|
||||
*
|
||||
* @param xQueue The handle to the queue on which the item is to be posted.
|
||||
*
|
||||
* @param pvItemToQueue A pointer to the item that is to be placed on the
|
||||
* queue. The size of the items the queue will hold was defined when the
|
||||
* queue was created, so this many bytes will be copied from pvItemToQueue
|
||||
* into the queue storage area.
|
||||
*
|
||||
* @param xCoRoutinePreviouslyWoken This is included so an ISR can post onto
|
||||
* the same queue multiple times from a single interrupt. The first call
|
||||
* should always pass in pdFALSE. Subsequent calls should pass in
|
||||
* the value returned from the previous call.
|
||||
*
|
||||
* @return pdTRUE if a co-routine was woken by posting onto the queue. This is
|
||||
* used by the ISR to determine if a context switch may be required following
|
||||
* the ISR.
|
||||
*
|
||||
* Example usage:
|
||||
<pre>
|
||||
// A co-routine that blocks on a queue waiting for characters to be received.
|
||||
static void vReceivingCoRoutine( CoRoutineHandle_t xHandle, UBaseType_t uxIndex )
|
||||
{
|
||||
char cRxedChar;
|
||||
BaseType_t xResult;
|
||||
|
||||
// All co-routines must start with a call to crSTART().
|
||||
crSTART( xHandle );
|
||||
|
||||
for( ;; )
|
||||
{
|
||||
// Wait for data to become available on the queue. This assumes the
|
||||
// queue xCommsRxQueue has already been created!
|
||||
crQUEUE_RECEIVE( xHandle, xCommsRxQueue, &uxLEDToFlash, portMAX_DELAY, &xResult );
|
||||
|
||||
// Was a character received?
|
||||
if( xResult == pdPASS )
|
||||
{
|
||||
// Process the character here.
|
||||
}
|
||||
}
|
||||
|
||||
// All co-routines must end with a call to crEND().
|
||||
crEND();
|
||||
}
|
||||
|
||||
// An ISR that uses a queue to send characters received on a serial port to
|
||||
// a co-routine.
|
||||
void vUART_ISR( void )
|
||||
{
|
||||
char cRxedChar;
|
||||
BaseType_t xCRWokenByPost = pdFALSE;
|
||||
|
||||
// We loop around reading characters until there are none left in the UART.
|
||||
while( UART_RX_REG_NOT_EMPTY() )
|
||||
{
|
||||
// Obtain the character from the UART.
|
||||
cRxedChar = UART_RX_REG;
|
||||
|
||||
// Post the character onto a queue. xCRWokenByPost will be pdFALSE
|
||||
// the first time around the loop. If the post causes a co-routine
|
||||
// to be woken (unblocked) then xCRWokenByPost will be set to pdTRUE.
|
||||
// In this manner we can ensure that if more than one co-routine is
|
||||
// blocked on the queue only one is woken by this ISR no matter how
|
||||
// many characters are posted to the queue.
|
||||
xCRWokenByPost = crQUEUE_SEND_FROM_ISR( xCommsRxQueue, &cRxedChar, xCRWokenByPost );
|
||||
}
|
||||
}</pre>
|
||||
* \defgroup crQUEUE_SEND_FROM_ISR crQUEUE_SEND_FROM_ISR
|
||||
* \ingroup Tasks
|
||||
*/
|
||||
#define crQUEUE_SEND_FROM_ISR( pxQueue, pvItemToQueue, xCoRoutinePreviouslyWoken ) xQueueCRSendFromISR( ( pxQueue ), ( pvItemToQueue ), ( xCoRoutinePreviouslyWoken ) )
|
||||
|
||||
|
||||
/**
|
||||
* croutine. h
|
||||
* <pre>
|
||||
crQUEUE_SEND_FROM_ISR(
|
||||
QueueHandle_t pxQueue,
|
||||
void *pvBuffer,
|
||||
BaseType_t * pxCoRoutineWoken
|
||||
)</pre>
|
||||
*
|
||||
* The macro's crQUEUE_SEND_FROM_ISR() and crQUEUE_RECEIVE_FROM_ISR() are the
|
||||
* co-routine equivalent to the xQueueSendFromISR() and xQueueReceiveFromISR()
|
||||
* functions used by tasks.
|
||||
*
|
||||
* crQUEUE_SEND_FROM_ISR() and crQUEUE_RECEIVE_FROM_ISR() can only be used to
|
||||
* pass data between a co-routine and and ISR, whereas xQueueSendFromISR() and
|
||||
* xQueueReceiveFromISR() can only be used to pass data between a task and and
|
||||
* ISR.
|
||||
*
|
||||
* crQUEUE_RECEIVE_FROM_ISR can only be called from an ISR to receive data
|
||||
* from a queue that is being used from within a co-routine (a co-routine
|
||||
* posted to the queue).
|
||||
*
|
||||
* See the co-routine section of the WEB documentation for information on
|
||||
* passing data between tasks and co-routines and between ISR's and
|
||||
* co-routines.
|
||||
*
|
||||
* @param xQueue The handle to the queue on which the item is to be posted.
|
||||
*
|
||||
* @param pvBuffer A pointer to a buffer into which the received item will be
|
||||
* placed. The size of the items the queue will hold was defined when the
|
||||
* queue was created, so this many bytes will be copied from the queue into
|
||||
* pvBuffer.
|
||||
*
|
||||
* @param pxCoRoutineWoken A co-routine may be blocked waiting for space to become
|
||||
* available on the queue. If crQUEUE_RECEIVE_FROM_ISR causes such a
|
||||
* co-routine to unblock *pxCoRoutineWoken will get set to pdTRUE, otherwise
|
||||
* *pxCoRoutineWoken will remain unchanged.
|
||||
*
|
||||
* @return pdTRUE an item was successfully received from the queue, otherwise
|
||||
* pdFALSE.
|
||||
*
|
||||
* Example usage:
|
||||
<pre>
|
||||
// A co-routine that posts a character to a queue then blocks for a fixed
|
||||
// period. The character is incremented each time.
|
||||
static void vSendingCoRoutine( CoRoutineHandle_t xHandle, UBaseType_t uxIndex )
|
||||
{
|
||||
// cChar holds its value while this co-routine is blocked and must therefore
|
||||
// be declared static.
|
||||
static char cCharToTx = 'a';
|
||||
BaseType_t xResult;
|
||||
|
||||
// All co-routines must start with a call to crSTART().
|
||||
crSTART( xHandle );
|
||||
|
||||
for( ;; )
|
||||
{
|
||||
// Send the next character to the queue.
|
||||
crQUEUE_SEND( xHandle, xCoRoutineQueue, &cCharToTx, NO_DELAY, &xResult );
|
||||
|
||||
if( xResult == pdPASS )
|
||||
{
|
||||
// The character was successfully posted to the queue.
|
||||
}
|
||||
else
|
||||
{
|
||||
// Could not post the character to the queue.
|
||||
}
|
||||
|
||||
// Enable the UART Tx interrupt to cause an interrupt in this
|
||||
// hypothetical UART. The interrupt will obtain the character
|
||||
// from the queue and send it.
|
||||
ENABLE_RX_INTERRUPT();
|
||||
|
||||
// Increment to the next character then block for a fixed period.
|
||||
// cCharToTx will maintain its value across the delay as it is
|
||||
// declared static.
|
||||
cCharToTx++;
|
||||
if( cCharToTx > 'x' )
|
||||
{
|
||||
cCharToTx = 'a';
|
||||
}
|
||||
crDELAY( 100 );
|
||||
}
|
||||
|
||||
// All co-routines must end with a call to crEND().
|
||||
crEND();
|
||||
}
|
||||
|
||||
// An ISR that uses a queue to receive characters to send on a UART.
|
||||
void vUART_ISR( void )
|
||||
{
|
||||
char cCharToTx;
|
||||
BaseType_t xCRWokenByPost = pdFALSE;
|
||||
|
||||
while( UART_TX_REG_EMPTY() )
|
||||
{
|
||||
// Are there any characters in the queue waiting to be sent?
|
||||
// xCRWokenByPost will automatically be set to pdTRUE if a co-routine
|
||||
// is woken by the post - ensuring that only a single co-routine is
|
||||
// woken no matter how many times we go around this loop.
|
||||
if( crQUEUE_RECEIVE_FROM_ISR( pxQueue, &cCharToTx, &xCRWokenByPost ) )
|
||||
{
|
||||
SEND_CHARACTER( cCharToTx );
|
||||
}
|
||||
}
|
||||
}</pre>
|
||||
* \defgroup crQUEUE_RECEIVE_FROM_ISR crQUEUE_RECEIVE_FROM_ISR
|
||||
* \ingroup Tasks
|
||||
*/
|
||||
#define crQUEUE_RECEIVE_FROM_ISR( pxQueue, pvBuffer, pxCoRoutineWoken ) xQueueCRReceiveFromISR( ( pxQueue ), ( pvBuffer ), ( pxCoRoutineWoken ) )
|
||||
|
||||
/*
|
||||
* This function is intended for internal use by the co-routine macros only.
|
||||
* The macro nature of the co-routine implementation requires that the
|
||||
* prototype appears here. The function should not be used by application
|
||||
* writers.
|
||||
*
|
||||
* Removes the current co-routine from its ready list and places it in the
|
||||
* appropriate delayed list.
|
||||
*/
|
||||
void vCoRoutineAddToDelayedList( TickType_t xTicksToDelay, List_t *pxEventList );
|
||||
|
||||
/*
|
||||
* This function is intended for internal use by the queue implementation only.
|
||||
* The function should not be used by application writers.
|
||||
*
|
||||
* Removes the highest priority co-routine from the event list and places it in
|
||||
* the pending ready list.
|
||||
*/
|
||||
BaseType_t xCoRoutineRemoveFromEventList( const List_t *pxEventList );
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* CO_ROUTINE_H */
|
||||
@@ -1,770 +0,0 @@
|
||||
/* Copyright 2018 Canaan Inc.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* http://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.
|
||||
*/
|
||||
/*
|
||||
* FreeRTOS Kernel V10.0.1
|
||||
* Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* http://www.FreeRTOS.org
|
||||
* http://aws.amazon.com/freertos
|
||||
*
|
||||
* 1 tab == 4 spaces!
|
||||
*/
|
||||
|
||||
#ifndef EVENT_GROUPS_H
|
||||
#define EVENT_GROUPS_H
|
||||
|
||||
#ifndef INC_FREERTOS_H
|
||||
#error "include FreeRTOS.h" must appear in source files before "include event_groups.h"
|
||||
#endif
|
||||
|
||||
/* FreeRTOS includes. */
|
||||
#include "timers.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* An event group is a collection of bits to which an application can assign a
|
||||
* meaning. For example, an application may create an event group to convey
|
||||
* the status of various CAN bus related events in which bit 0 might mean "A CAN
|
||||
* message has been received and is ready for processing", bit 1 might mean "The
|
||||
* application has queued a message that is ready for sending onto the CAN
|
||||
* network", and bit 2 might mean "It is time to send a SYNC message onto the
|
||||
* CAN network" etc. A task can then test the bit values to see which events
|
||||
* are active, and optionally enter the Blocked state to wait for a specified
|
||||
* bit or a group of specified bits to be active. To continue the CAN bus
|
||||
* example, a CAN controlling task can enter the Blocked state (and therefore
|
||||
* not consume any processing time) until either bit 0, bit 1 or bit 2 are
|
||||
* active, at which time the bit that was actually active would inform the task
|
||||
* which action it had to take (process a received message, send a message, or
|
||||
* send a SYNC).
|
||||
*
|
||||
* The event groups implementation contains intelligence to avoid race
|
||||
* conditions that would otherwise occur were an application to use a simple
|
||||
* variable for the same purpose. This is particularly important with respect
|
||||
* to when a bit within an event group is to be cleared, and when bits have to
|
||||
* be set and then tested atomically - as is the case where event groups are
|
||||
* used to create a synchronisation point between multiple tasks (a
|
||||
* 'rendezvous').
|
||||
*
|
||||
* \defgroup EventGroup
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* event_groups.h
|
||||
*
|
||||
* Type by which event groups are referenced. For example, a call to
|
||||
* xEventGroupCreate() returns an EventGroupHandle_t variable that can then
|
||||
* be used as a parameter to other event group functions.
|
||||
*
|
||||
* \defgroup EventGroupHandle_t EventGroupHandle_t
|
||||
* \ingroup EventGroup
|
||||
*/
|
||||
typedef void * EventGroupHandle_t;
|
||||
|
||||
/*
|
||||
* The type that holds event bits always matches TickType_t - therefore the
|
||||
* number of bits it holds is set by configUSE_16_BIT_TICKS (16 bits if set to 1,
|
||||
* 32 bits if set to 0.
|
||||
*
|
||||
* \defgroup EventBits_t EventBits_t
|
||||
* \ingroup EventGroup
|
||||
*/
|
||||
typedef TickType_t EventBits_t;
|
||||
|
||||
/**
|
||||
* event_groups.h
|
||||
*<pre>
|
||||
EventGroupHandle_t xEventGroupCreate( void );
|
||||
</pre>
|
||||
*
|
||||
* Create a new event group.
|
||||
*
|
||||
* Internally, within the FreeRTOS implementation, event groups use a [small]
|
||||
* block of memory, in which the event group's structure is stored. If an event
|
||||
* groups is created using xEventGropuCreate() then the required memory is
|
||||
* automatically dynamically allocated inside the xEventGroupCreate() function.
|
||||
* (see http://www.freertos.org/a00111.html). If an event group is created
|
||||
* using xEventGropuCreateStatic() then the application writer must instead
|
||||
* provide the memory that will get used by the event group.
|
||||
* xEventGroupCreateStatic() therefore allows an event group to be created
|
||||
* without using any dynamic memory allocation.
|
||||
*
|
||||
* Although event groups are not related to ticks, for internal implementation
|
||||
* reasons the number of bits available for use in an event group is dependent
|
||||
* on the configUSE_16_BIT_TICKS setting in FreeRTOSConfig.h. If
|
||||
* configUSE_16_BIT_TICKS is 1 then each event group contains 8 usable bits (bit
|
||||
* 0 to bit 7). If configUSE_16_BIT_TICKS is set to 0 then each event group has
|
||||
* 24 usable bits (bit 0 to bit 23). The EventBits_t type is used to store
|
||||
* event bits within an event group.
|
||||
*
|
||||
* @return If the event group was created then a handle to the event group is
|
||||
* returned. If there was insufficient FreeRTOS heap available to create the
|
||||
* event group then NULL is returned. See http://www.freertos.org/a00111.html
|
||||
*
|
||||
* Example usage:
|
||||
<pre>
|
||||
// Declare a variable to hold the created event group.
|
||||
EventGroupHandle_t xCreatedEventGroup;
|
||||
|
||||
// Attempt to create the event group.
|
||||
xCreatedEventGroup = xEventGroupCreate();
|
||||
|
||||
// Was the event group created successfully?
|
||||
if( xCreatedEventGroup == NULL )
|
||||
{
|
||||
// The event group was not created because there was insufficient
|
||||
// FreeRTOS heap available.
|
||||
}
|
||||
else
|
||||
{
|
||||
// The event group was created.
|
||||
}
|
||||
</pre>
|
||||
* \defgroup xEventGroupCreate xEventGroupCreate
|
||||
* \ingroup EventGroup
|
||||
*/
|
||||
#if( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
|
||||
EventGroupHandle_t xEventGroupCreate( void ) PRIVILEGED_FUNCTION;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* event_groups.h
|
||||
*<pre>
|
||||
EventGroupHandle_t xEventGroupCreateStatic( EventGroupHandle_t * pxEventGroupBuffer );
|
||||
</pre>
|
||||
*
|
||||
* Create a new event group.
|
||||
*
|
||||
* Internally, within the FreeRTOS implementation, event groups use a [small]
|
||||
* block of memory, in which the event group's structure is stored. If an event
|
||||
* groups is created using xEventGropuCreate() then the required memory is
|
||||
* automatically dynamically allocated inside the xEventGroupCreate() function.
|
||||
* (see http://www.freertos.org/a00111.html). If an event group is created
|
||||
* using xEventGropuCreateStatic() then the application writer must instead
|
||||
* provide the memory that will get used by the event group.
|
||||
* xEventGroupCreateStatic() therefore allows an event group to be created
|
||||
* without using any dynamic memory allocation.
|
||||
*
|
||||
* Although event groups are not related to ticks, for internal implementation
|
||||
* reasons the number of bits available for use in an event group is dependent
|
||||
* on the configUSE_16_BIT_TICKS setting in FreeRTOSConfig.h. If
|
||||
* configUSE_16_BIT_TICKS is 1 then each event group contains 8 usable bits (bit
|
||||
* 0 to bit 7). If configUSE_16_BIT_TICKS is set to 0 then each event group has
|
||||
* 24 usable bits (bit 0 to bit 23). The EventBits_t type is used to store
|
||||
* event bits within an event group.
|
||||
*
|
||||
* @param pxEventGroupBuffer pxEventGroupBuffer must point to a variable of type
|
||||
* StaticEventGroup_t, which will be then be used to hold the event group's data
|
||||
* structures, removing the need for the memory to be allocated dynamically.
|
||||
*
|
||||
* @return If the event group was created then a handle to the event group is
|
||||
* returned. If pxEventGroupBuffer was NULL then NULL is returned.
|
||||
*
|
||||
* Example usage:
|
||||
<pre>
|
||||
// StaticEventGroup_t is a publicly accessible structure that has the same
|
||||
// size and alignment requirements as the real event group structure. It is
|
||||
// provided as a mechanism for applications to know the size of the event
|
||||
// group (which is dependent on the architecture and configuration file
|
||||
// settings) without breaking the strict data hiding policy by exposing the
|
||||
// real event group internals. This StaticEventGroup_t variable is passed
|
||||
// into the xSemaphoreCreateEventGroupStatic() function and is used to store
|
||||
// the event group's data structures
|
||||
StaticEventGroup_t xEventGroupBuffer;
|
||||
|
||||
// Create the event group without dynamically allocating any memory.
|
||||
xEventGroup = xEventGroupCreateStatic( &xEventGroupBuffer );
|
||||
</pre>
|
||||
*/
|
||||
#if( configSUPPORT_STATIC_ALLOCATION == 1 )
|
||||
EventGroupHandle_t xEventGroupCreateStatic( StaticEventGroup_t *pxEventGroupBuffer ) PRIVILEGED_FUNCTION;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* event_groups.h
|
||||
*<pre>
|
||||
EventBits_t xEventGroupWaitBits( EventGroupHandle_t xEventGroup,
|
||||
const EventBits_t uxBitsToWaitFor,
|
||||
const BaseType_t xClearOnExit,
|
||||
const BaseType_t xWaitForAllBits,
|
||||
const TickType_t xTicksToWait );
|
||||
</pre>
|
||||
*
|
||||
* [Potentially] block to wait for one or more bits to be set within a
|
||||
* previously created event group.
|
||||
*
|
||||
* This function cannot be called from an interrupt.
|
||||
*
|
||||
* @param xEventGroup The event group in which the bits are being tested. The
|
||||
* event group must have previously been created using a call to
|
||||
* xEventGroupCreate().
|
||||
*
|
||||
* @param uxBitsToWaitFor A bitwise value that indicates the bit or bits to test
|
||||
* inside the event group. For example, to wait for bit 0 and/or bit 2 set
|
||||
* uxBitsToWaitFor to 0x05. To wait for bits 0 and/or bit 1 and/or bit 2 set
|
||||
* uxBitsToWaitFor to 0x07. Etc.
|
||||
*
|
||||
* @param xClearOnExit If xClearOnExit is set to pdTRUE then any bits within
|
||||
* uxBitsToWaitFor that are set within the event group will be cleared before
|
||||
* xEventGroupWaitBits() returns if the wait condition was met (if the function
|
||||
* returns for a reason other than a timeout). If xClearOnExit is set to
|
||||
* pdFALSE then the bits set in the event group are not altered when the call to
|
||||
* xEventGroupWaitBits() returns.
|
||||
*
|
||||
* @param xWaitForAllBits If xWaitForAllBits is set to pdTRUE then
|
||||
* xEventGroupWaitBits() will return when either all the bits in uxBitsToWaitFor
|
||||
* are set or the specified block time expires. If xWaitForAllBits is set to
|
||||
* pdFALSE then xEventGroupWaitBits() will return when any one of the bits set
|
||||
* in uxBitsToWaitFor is set or the specified block time expires. The block
|
||||
* time is specified by the xTicksToWait parameter.
|
||||
*
|
||||
* @param xTicksToWait The maximum amount of time (specified in 'ticks') to wait
|
||||
* for one/all (depending on the xWaitForAllBits value) of the bits specified by
|
||||
* uxBitsToWaitFor to become set.
|
||||
*
|
||||
* @return The value of the event group at the time either the bits being waited
|
||||
* for became set, or the block time expired. Test the return value to know
|
||||
* which bits were set. If xEventGroupWaitBits() returned because its timeout
|
||||
* expired then not all the bits being waited for will be set. If
|
||||
* xEventGroupWaitBits() returned because the bits it was waiting for were set
|
||||
* then the returned value is the event group value before any bits were
|
||||
* automatically cleared in the case that xClearOnExit parameter was set to
|
||||
* pdTRUE.
|
||||
*
|
||||
* Example usage:
|
||||
<pre>
|
||||
#define BIT_0 ( 1 << 0 )
|
||||
#define BIT_4 ( 1 << 4 )
|
||||
|
||||
void aFunction( EventGroupHandle_t xEventGroup )
|
||||
{
|
||||
EventBits_t uxBits;
|
||||
const TickType_t xTicksToWait = 100 / portTICK_PERIOD_MS;
|
||||
|
||||
// Wait a maximum of 100ms for either bit 0 or bit 4 to be set within
|
||||
// the event group. Clear the bits before exiting.
|
||||
uxBits = xEventGroupWaitBits(
|
||||
xEventGroup, // The event group being tested.
|
||||
BIT_0 | BIT_4, // The bits within the event group to wait for.
|
||||
pdTRUE, // BIT_0 and BIT_4 should be cleared before returning.
|
||||
pdFALSE, // Don't wait for both bits, either bit will do.
|
||||
xTicksToWait ); // Wait a maximum of 100ms for either bit to be set.
|
||||
|
||||
if( ( uxBits & ( BIT_0 | BIT_4 ) ) == ( BIT_0 | BIT_4 ) )
|
||||
{
|
||||
// xEventGroupWaitBits() returned because both bits were set.
|
||||
}
|
||||
else if( ( uxBits & BIT_0 ) != 0 )
|
||||
{
|
||||
// xEventGroupWaitBits() returned because just BIT_0 was set.
|
||||
}
|
||||
else if( ( uxBits & BIT_4 ) != 0 )
|
||||
{
|
||||
// xEventGroupWaitBits() returned because just BIT_4 was set.
|
||||
}
|
||||
else
|
||||
{
|
||||
// xEventGroupWaitBits() returned because xTicksToWait ticks passed
|
||||
// without either BIT_0 or BIT_4 becoming set.
|
||||
}
|
||||
}
|
||||
</pre>
|
||||
* \defgroup xEventGroupWaitBits xEventGroupWaitBits
|
||||
* \ingroup EventGroup
|
||||
*/
|
||||
EventBits_t xEventGroupWaitBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToWaitFor, const BaseType_t xClearOnExit, const BaseType_t xWaitForAllBits, TickType_t xTicksToWait ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/**
|
||||
* event_groups.h
|
||||
*<pre>
|
||||
EventBits_t xEventGroupClearBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToClear );
|
||||
</pre>
|
||||
*
|
||||
* Clear bits within an event group. This function cannot be called from an
|
||||
* interrupt.
|
||||
*
|
||||
* @param xEventGroup The event group in which the bits are to be cleared.
|
||||
*
|
||||
* @param uxBitsToClear A bitwise value that indicates the bit or bits to clear
|
||||
* in the event group. For example, to clear bit 3 only, set uxBitsToClear to
|
||||
* 0x08. To clear bit 3 and bit 0 set uxBitsToClear to 0x09.
|
||||
*
|
||||
* @return The value of the event group before the specified bits were cleared.
|
||||
*
|
||||
* Example usage:
|
||||
<pre>
|
||||
#define BIT_0 ( 1 << 0 )
|
||||
#define BIT_4 ( 1 << 4 )
|
||||
|
||||
void aFunction( EventGroupHandle_t xEventGroup )
|
||||
{
|
||||
EventBits_t uxBits;
|
||||
|
||||
// Clear bit 0 and bit 4 in xEventGroup.
|
||||
uxBits = xEventGroupClearBits(
|
||||
xEventGroup, // The event group being updated.
|
||||
BIT_0 | BIT_4 );// The bits being cleared.
|
||||
|
||||
if( ( uxBits & ( BIT_0 | BIT_4 ) ) == ( BIT_0 | BIT_4 ) )
|
||||
{
|
||||
// Both bit 0 and bit 4 were set before xEventGroupClearBits() was
|
||||
// called. Both will now be clear (not set).
|
||||
}
|
||||
else if( ( uxBits & BIT_0 ) != 0 )
|
||||
{
|
||||
// Bit 0 was set before xEventGroupClearBits() was called. It will
|
||||
// now be clear.
|
||||
}
|
||||
else if( ( uxBits & BIT_4 ) != 0 )
|
||||
{
|
||||
// Bit 4 was set before xEventGroupClearBits() was called. It will
|
||||
// now be clear.
|
||||
}
|
||||
else
|
||||
{
|
||||
// Neither bit 0 nor bit 4 were set in the first place.
|
||||
}
|
||||
}
|
||||
</pre>
|
||||
* \defgroup xEventGroupClearBits xEventGroupClearBits
|
||||
* \ingroup EventGroup
|
||||
*/
|
||||
EventBits_t xEventGroupClearBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToClear ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/**
|
||||
* event_groups.h
|
||||
*<pre>
|
||||
BaseType_t xEventGroupClearBitsFromISR( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet );
|
||||
</pre>
|
||||
*
|
||||
* A version of xEventGroupClearBits() that can be called from an interrupt.
|
||||
*
|
||||
* Setting bits in an event group is not a deterministic operation because there
|
||||
* are an unknown number of tasks that may be waiting for the bit or bits being
|
||||
* set. FreeRTOS does not allow nondeterministic operations to be performed
|
||||
* while interrupts are disabled, so protects event groups that are accessed
|
||||
* from tasks by suspending the scheduler rather than disabling interrupts. As
|
||||
* a result event groups cannot be accessed directly from an interrupt service
|
||||
* routine. Therefore xEventGroupClearBitsFromISR() sends a message to the
|
||||
* timer task to have the clear operation performed in the context of the timer
|
||||
* task.
|
||||
*
|
||||
* @param xEventGroup The event group in which the bits are to be cleared.
|
||||
*
|
||||
* @param uxBitsToClear A bitwise value that indicates the bit or bits to clear.
|
||||
* For example, to clear bit 3 only, set uxBitsToClear to 0x08. To clear bit 3
|
||||
* and bit 0 set uxBitsToClear to 0x09.
|
||||
*
|
||||
* @return If the request to execute the function was posted successfully then
|
||||
* pdPASS is returned, otherwise pdFALSE is returned. pdFALSE will be returned
|
||||
* if the timer service queue was full.
|
||||
*
|
||||
* Example usage:
|
||||
<pre>
|
||||
#define BIT_0 ( 1 << 0 )
|
||||
#define BIT_4 ( 1 << 4 )
|
||||
|
||||
// An event group which it is assumed has already been created by a call to
|
||||
// xEventGroupCreate().
|
||||
EventGroupHandle_t xEventGroup;
|
||||
|
||||
void anInterruptHandler( void )
|
||||
{
|
||||
// Clear bit 0 and bit 4 in xEventGroup.
|
||||
xResult = xEventGroupClearBitsFromISR(
|
||||
xEventGroup, // The event group being updated.
|
||||
BIT_0 | BIT_4 ); // The bits being set.
|
||||
|
||||
if( xResult == pdPASS )
|
||||
{
|
||||
// The message was posted successfully.
|
||||
}
|
||||
}
|
||||
</pre>
|
||||
* \defgroup xEventGroupClearBitsFromISR xEventGroupClearBitsFromISR
|
||||
* \ingroup EventGroup
|
||||
*/
|
||||
#if( configUSE_TRACE_FACILITY == 1 )
|
||||
BaseType_t xEventGroupClearBitsFromISR( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet ) PRIVILEGED_FUNCTION;
|
||||
#else
|
||||
#define xEventGroupClearBitsFromISR( xEventGroup, uxBitsToClear ) xTimerPendFunctionCallFromISR( vEventGroupClearBitsCallback, ( void * ) xEventGroup, ( uint32_t ) uxBitsToClear, NULL )
|
||||
#endif
|
||||
|
||||
/**
|
||||
* event_groups.h
|
||||
*<pre>
|
||||
EventBits_t xEventGroupSetBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet );
|
||||
</pre>
|
||||
*
|
||||
* Set bits within an event group.
|
||||
* This function cannot be called from an interrupt. xEventGroupSetBitsFromISR()
|
||||
* is a version that can be called from an interrupt.
|
||||
*
|
||||
* Setting bits in an event group will automatically unblock tasks that are
|
||||
* blocked waiting for the bits.
|
||||
*
|
||||
* @param xEventGroup The event group in which the bits are to be set.
|
||||
*
|
||||
* @param uxBitsToSet A bitwise value that indicates the bit or bits to set.
|
||||
* For example, to set bit 3 only, set uxBitsToSet to 0x08. To set bit 3
|
||||
* and bit 0 set uxBitsToSet to 0x09.
|
||||
*
|
||||
* @return The value of the event group at the time the call to
|
||||
* xEventGroupSetBits() returns. There are two reasons why the returned value
|
||||
* might have the bits specified by the uxBitsToSet parameter cleared. First,
|
||||
* if setting a bit results in a task that was waiting for the bit leaving the
|
||||
* blocked state then it is possible the bit will be cleared automatically
|
||||
* (see the xClearBitOnExit parameter of xEventGroupWaitBits()). Second, any
|
||||
* unblocked (or otherwise Ready state) task that has a priority above that of
|
||||
* the task that called xEventGroupSetBits() will execute and may change the
|
||||
* event group value before the call to xEventGroupSetBits() returns.
|
||||
*
|
||||
* Example usage:
|
||||
<pre>
|
||||
#define BIT_0 ( 1 << 0 )
|
||||
#define BIT_4 ( 1 << 4 )
|
||||
|
||||
void aFunction( EventGroupHandle_t xEventGroup )
|
||||
{
|
||||
EventBits_t uxBits;
|
||||
|
||||
// Set bit 0 and bit 4 in xEventGroup.
|
||||
uxBits = xEventGroupSetBits(
|
||||
xEventGroup, // The event group being updated.
|
||||
BIT_0 | BIT_4 );// The bits being set.
|
||||
|
||||
if( ( uxBits & ( BIT_0 | BIT_4 ) ) == ( BIT_0 | BIT_4 ) )
|
||||
{
|
||||
// Both bit 0 and bit 4 remained set when the function returned.
|
||||
}
|
||||
else if( ( uxBits & BIT_0 ) != 0 )
|
||||
{
|
||||
// Bit 0 remained set when the function returned, but bit 4 was
|
||||
// cleared. It might be that bit 4 was cleared automatically as a
|
||||
// task that was waiting for bit 4 was removed from the Blocked
|
||||
// state.
|
||||
}
|
||||
else if( ( uxBits & BIT_4 ) != 0 )
|
||||
{
|
||||
// Bit 4 remained set when the function returned, but bit 0 was
|
||||
// cleared. It might be that bit 0 was cleared automatically as a
|
||||
// task that was waiting for bit 0 was removed from the Blocked
|
||||
// state.
|
||||
}
|
||||
else
|
||||
{
|
||||
// Neither bit 0 nor bit 4 remained set. It might be that a task
|
||||
// was waiting for both of the bits to be set, and the bits were
|
||||
// cleared as the task left the Blocked state.
|
||||
}
|
||||
}
|
||||
</pre>
|
||||
* \defgroup xEventGroupSetBits xEventGroupSetBits
|
||||
* \ingroup EventGroup
|
||||
*/
|
||||
EventBits_t xEventGroupSetBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/**
|
||||
* event_groups.h
|
||||
*<pre>
|
||||
BaseType_t xEventGroupSetBitsFromISR( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet, BaseType_t *pxHigherPriorityTaskWoken );
|
||||
</pre>
|
||||
*
|
||||
* A version of xEventGroupSetBits() that can be called from an interrupt.
|
||||
*
|
||||
* Setting bits in an event group is not a deterministic operation because there
|
||||
* are an unknown number of tasks that may be waiting for the bit or bits being
|
||||
* set. FreeRTOS does not allow nondeterministic operations to be performed in
|
||||
* interrupts or from critical sections. Therefore xEventGroupSetBitsFromISR()
|
||||
* sends a message to the timer task to have the set operation performed in the
|
||||
* context of the timer task - where a scheduler lock is used in place of a
|
||||
* critical section.
|
||||
*
|
||||
* @param xEventGroup The event group in which the bits are to be set.
|
||||
*
|
||||
* @param uxBitsToSet A bitwise value that indicates the bit or bits to set.
|
||||
* For example, to set bit 3 only, set uxBitsToSet to 0x08. To set bit 3
|
||||
* and bit 0 set uxBitsToSet to 0x09.
|
||||
*
|
||||
* @param pxHigherPriorityTaskWoken As mentioned above, calling this function
|
||||
* will result in a message being sent to the timer daemon task. If the
|
||||
* priority of the timer daemon task is higher than the priority of the
|
||||
* currently running task (the task the interrupt interrupted) then
|
||||
* *pxHigherPriorityTaskWoken will be set to pdTRUE by
|
||||
* xEventGroupSetBitsFromISR(), indicating that a context switch should be
|
||||
* requested before the interrupt exits. For that reason
|
||||
* *pxHigherPriorityTaskWoken must be initialised to pdFALSE. See the
|
||||
* example code below.
|
||||
*
|
||||
* @return If the request to execute the function was posted successfully then
|
||||
* pdPASS is returned, otherwise pdFALSE is returned. pdFALSE will be returned
|
||||
* if the timer service queue was full.
|
||||
*
|
||||
* Example usage:
|
||||
<pre>
|
||||
#define BIT_0 ( 1 << 0 )
|
||||
#define BIT_4 ( 1 << 4 )
|
||||
|
||||
// An event group which it is assumed has already been created by a call to
|
||||
// xEventGroupCreate().
|
||||
EventGroupHandle_t xEventGroup;
|
||||
|
||||
void anInterruptHandler( void )
|
||||
{
|
||||
BaseType_t xHigherPriorityTaskWoken, xResult;
|
||||
|
||||
// xHigherPriorityTaskWoken must be initialised to pdFALSE.
|
||||
xHigherPriorityTaskWoken = pdFALSE;
|
||||
|
||||
// Set bit 0 and bit 4 in xEventGroup.
|
||||
xResult = xEventGroupSetBitsFromISR(
|
||||
xEventGroup, // The event group being updated.
|
||||
BIT_0 | BIT_4 // The bits being set.
|
||||
&xHigherPriorityTaskWoken );
|
||||
|
||||
// Was the message posted successfully?
|
||||
if( xResult == pdPASS )
|
||||
{
|
||||
// If xHigherPriorityTaskWoken is now set to pdTRUE then a context
|
||||
// switch should be requested. The macro used is port specific and
|
||||
// will be either portYIELD_FROM_ISR() or portEND_SWITCHING_ISR() -
|
||||
// refer to the documentation page for the port being used.
|
||||
portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
|
||||
}
|
||||
}
|
||||
</pre>
|
||||
* \defgroup xEventGroupSetBitsFromISR xEventGroupSetBitsFromISR
|
||||
* \ingroup EventGroup
|
||||
*/
|
||||
#if( configUSE_TRACE_FACILITY == 1 )
|
||||
BaseType_t xEventGroupSetBitsFromISR( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet, BaseType_t *pxHigherPriorityTaskWoken ) PRIVILEGED_FUNCTION;
|
||||
#else
|
||||
#define xEventGroupSetBitsFromISR( xEventGroup, uxBitsToSet, pxHigherPriorityTaskWoken ) xTimerPendFunctionCallFromISR( vEventGroupSetBitsCallback, ( void * ) xEventGroup, ( uint32_t ) uxBitsToSet, pxHigherPriorityTaskWoken )
|
||||
#endif
|
||||
|
||||
/**
|
||||
* event_groups.h
|
||||
*<pre>
|
||||
EventBits_t xEventGroupSync( EventGroupHandle_t xEventGroup,
|
||||
const EventBits_t uxBitsToSet,
|
||||
const EventBits_t uxBitsToWaitFor,
|
||||
TickType_t xTicksToWait );
|
||||
</pre>
|
||||
*
|
||||
* Atomically set bits within an event group, then wait for a combination of
|
||||
* bits to be set within the same event group. This functionality is typically
|
||||
* used to synchronise multiple tasks, where each task has to wait for the other
|
||||
* tasks to reach a synchronisation point before proceeding.
|
||||
*
|
||||
* This function cannot be used from an interrupt.
|
||||
*
|
||||
* The function will return before its block time expires if the bits specified
|
||||
* by the uxBitsToWait parameter are set, or become set within that time. In
|
||||
* this case all the bits specified by uxBitsToWait will be automatically
|
||||
* cleared before the function returns.
|
||||
*
|
||||
* @param xEventGroup The event group in which the bits are being tested. The
|
||||
* event group must have previously been created using a call to
|
||||
* xEventGroupCreate().
|
||||
*
|
||||
* @param uxBitsToSet The bits to set in the event group before determining
|
||||
* if, and possibly waiting for, all the bits specified by the uxBitsToWait
|
||||
* parameter are set.
|
||||
*
|
||||
* @param uxBitsToWaitFor A bitwise value that indicates the bit or bits to test
|
||||
* inside the event group. For example, to wait for bit 0 and bit 2 set
|
||||
* uxBitsToWaitFor to 0x05. To wait for bits 0 and bit 1 and bit 2 set
|
||||
* uxBitsToWaitFor to 0x07. Etc.
|
||||
*
|
||||
* @param xTicksToWait The maximum amount of time (specified in 'ticks') to wait
|
||||
* for all of the bits specified by uxBitsToWaitFor to become set.
|
||||
*
|
||||
* @return The value of the event group at the time either the bits being waited
|
||||
* for became set, or the block time expired. Test the return value to know
|
||||
* which bits were set. If xEventGroupSync() returned because its timeout
|
||||
* expired then not all the bits being waited for will be set. If
|
||||
* xEventGroupSync() returned because all the bits it was waiting for were
|
||||
* set then the returned value is the event group value before any bits were
|
||||
* automatically cleared.
|
||||
*
|
||||
* Example usage:
|
||||
<pre>
|
||||
// Bits used by the three tasks.
|
||||
#define TASK_0_BIT ( 1 << 0 )
|
||||
#define TASK_1_BIT ( 1 << 1 )
|
||||
#define TASK_2_BIT ( 1 << 2 )
|
||||
|
||||
#define ALL_SYNC_BITS ( TASK_0_BIT | TASK_1_BIT | TASK_2_BIT )
|
||||
|
||||
// Use an event group to synchronise three tasks. It is assumed this event
|
||||
// group has already been created elsewhere.
|
||||
EventGroupHandle_t xEventBits;
|
||||
|
||||
void vTask0( void *pvParameters )
|
||||
{
|
||||
EventBits_t uxReturn;
|
||||
TickType_t xTicksToWait = 100 / portTICK_PERIOD_MS;
|
||||
|
||||
for( ;; )
|
||||
{
|
||||
// Perform task functionality here.
|
||||
|
||||
// Set bit 0 in the event flag to note this task has reached the
|
||||
// sync point. The other two tasks will set the other two bits defined
|
||||
// by ALL_SYNC_BITS. All three tasks have reached the synchronisation
|
||||
// point when all the ALL_SYNC_BITS are set. Wait a maximum of 100ms
|
||||
// for this to happen.
|
||||
uxReturn = xEventGroupSync( xEventBits, TASK_0_BIT, ALL_SYNC_BITS, xTicksToWait );
|
||||
|
||||
if( ( uxReturn & ALL_SYNC_BITS ) == ALL_SYNC_BITS )
|
||||
{
|
||||
// All three tasks reached the synchronisation point before the call
|
||||
// to xEventGroupSync() timed out.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void vTask1( void *pvParameters )
|
||||
{
|
||||
for( ;; )
|
||||
{
|
||||
// Perform task functionality here.
|
||||
|
||||
// Set bit 1 in the event flag to note this task has reached the
|
||||
// synchronisation point. The other two tasks will set the other two
|
||||
// bits defined by ALL_SYNC_BITS. All three tasks have reached the
|
||||
// synchronisation point when all the ALL_SYNC_BITS are set. Wait
|
||||
// indefinitely for this to happen.
|
||||
xEventGroupSync( xEventBits, TASK_1_BIT, ALL_SYNC_BITS, portMAX_DELAY );
|
||||
|
||||
// xEventGroupSync() was called with an indefinite block time, so
|
||||
// this task will only reach here if the syncrhonisation was made by all
|
||||
// three tasks, so there is no need to test the return value.
|
||||
}
|
||||
}
|
||||
|
||||
void vTask2( void *pvParameters )
|
||||
{
|
||||
for( ;; )
|
||||
{
|
||||
// Perform task functionality here.
|
||||
|
||||
// Set bit 2 in the event flag to note this task has reached the
|
||||
// synchronisation point. The other two tasks will set the other two
|
||||
// bits defined by ALL_SYNC_BITS. All three tasks have reached the
|
||||
// synchronisation point when all the ALL_SYNC_BITS are set. Wait
|
||||
// indefinitely for this to happen.
|
||||
xEventGroupSync( xEventBits, TASK_2_BIT, ALL_SYNC_BITS, portMAX_DELAY );
|
||||
|
||||
// xEventGroupSync() was called with an indefinite block time, so
|
||||
// this task will only reach here if the syncrhonisation was made by all
|
||||
// three tasks, so there is no need to test the return value.
|
||||
}
|
||||
}
|
||||
|
||||
</pre>
|
||||
* \defgroup xEventGroupSync xEventGroupSync
|
||||
* \ingroup EventGroup
|
||||
*/
|
||||
EventBits_t xEventGroupSync( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet, const EventBits_t uxBitsToWaitFor, TickType_t xTicksToWait ) PRIVILEGED_FUNCTION;
|
||||
|
||||
|
||||
/**
|
||||
* event_groups.h
|
||||
*<pre>
|
||||
EventBits_t xEventGroupGetBits( EventGroupHandle_t xEventGroup );
|
||||
</pre>
|
||||
*
|
||||
* Returns the current value of the bits in an event group. This function
|
||||
* cannot be used from an interrupt.
|
||||
*
|
||||
* @param xEventGroup The event group being queried.
|
||||
*
|
||||
* @return The event group bits at the time xEventGroupGetBits() was called.
|
||||
*
|
||||
* \defgroup xEventGroupGetBits xEventGroupGetBits
|
||||
* \ingroup EventGroup
|
||||
*/
|
||||
#define xEventGroupGetBits( xEventGroup ) xEventGroupClearBits( xEventGroup, 0 )
|
||||
|
||||
/**
|
||||
* event_groups.h
|
||||
*<pre>
|
||||
EventBits_t xEventGroupGetBitsFromISR( EventGroupHandle_t xEventGroup );
|
||||
</pre>
|
||||
*
|
||||
* A version of xEventGroupGetBits() that can be called from an ISR.
|
||||
*
|
||||
* @param xEventGroup The event group being queried.
|
||||
*
|
||||
* @return The event group bits at the time xEventGroupGetBitsFromISR() was called.
|
||||
*
|
||||
* \defgroup xEventGroupGetBitsFromISR xEventGroupGetBitsFromISR
|
||||
* \ingroup EventGroup
|
||||
*/
|
||||
EventBits_t xEventGroupGetBitsFromISR( EventGroupHandle_t xEventGroup ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/**
|
||||
* event_groups.h
|
||||
*<pre>
|
||||
void xEventGroupDelete( EventGroupHandle_t xEventGroup );
|
||||
</pre>
|
||||
*
|
||||
* Delete an event group that was previously created by a call to
|
||||
* xEventGroupCreate(). Tasks that are blocked on the event group will be
|
||||
* unblocked and obtain 0 as the event group's value.
|
||||
*
|
||||
* @param xEventGroup The event group being deleted.
|
||||
*/
|
||||
void vEventGroupDelete( EventGroupHandle_t xEventGroup ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/* For internal use only. */
|
||||
void vEventGroupSetBitsCallback( void *pvEventGroup, const uint32_t ulBitsToSet ) PRIVILEGED_FUNCTION;
|
||||
void vEventGroupClearBitsCallback( void *pvEventGroup, const uint32_t ulBitsToClear ) PRIVILEGED_FUNCTION;
|
||||
|
||||
|
||||
#if (configUSE_TRACE_FACILITY == 1)
|
||||
UBaseType_t uxEventGroupGetNumber( void* xEventGroup ) PRIVILEGED_FUNCTION;
|
||||
void vEventGroupSetNumber( void* xEventGroup, UBaseType_t uxEventGroupNumber ) PRIVILEGED_FUNCTION;
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* EVENT_GROUPS_H */
|
||||
|
||||
|
||||
@@ -1,425 +0,0 @@
|
||||
/* Copyright 2018 Canaan Inc.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* http://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.
|
||||
*/
|
||||
/*
|
||||
* FreeRTOS Kernel V10.0.1
|
||||
* Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* http://www.FreeRTOS.org
|
||||
* http://aws.amazon.com/freertos
|
||||
*
|
||||
* 1 tab == 4 spaces!
|
||||
*/
|
||||
|
||||
/*
|
||||
* This is the list implementation used by the scheduler. While it is tailored
|
||||
* heavily for the schedulers needs, it is also available for use by
|
||||
* application code.
|
||||
*
|
||||
* list_ts can only store pointers to list_item_ts. Each ListItem_t contains a
|
||||
* numeric value (xItemValue). Most of the time the lists are sorted in
|
||||
* descending item value order.
|
||||
*
|
||||
* Lists are created already containing one list item. The value of this
|
||||
* item is the maximum possible that can be stored, it is therefore always at
|
||||
* the end of the list and acts as a marker. The list member pxHead always
|
||||
* points to this marker - even though it is at the tail of the list. This
|
||||
* is because the tail contains a wrap back pointer to the true head of
|
||||
* the list.
|
||||
*
|
||||
* In addition to it's value, each list item contains a pointer to the next
|
||||
* item in the list (pxNext), a pointer to the list it is in (pxContainer)
|
||||
* and a pointer to back to the object that contains it. These later two
|
||||
* pointers are included for efficiency of list manipulation. There is
|
||||
* effectively a two way link between the object containing the list item and
|
||||
* the list item itself.
|
||||
*
|
||||
*
|
||||
* \page ListIntroduction List Implementation
|
||||
* \ingroup FreeRTOSIntro
|
||||
*/
|
||||
|
||||
#ifndef INC_FREERTOS_H
|
||||
#error FreeRTOS.h must be included before list.h
|
||||
#endif
|
||||
|
||||
#ifndef LIST_H
|
||||
#define LIST_H
|
||||
|
||||
/*
|
||||
* The list structure members are modified from within interrupts, and therefore
|
||||
* by rights should be declared volatile. However, they are only modified in a
|
||||
* functionally atomic way (within critical sections of with the scheduler
|
||||
* suspended) and are either passed by reference into a function or indexed via
|
||||
* a volatile variable. Therefore, in all use cases tested so far, the volatile
|
||||
* qualifier can be omitted in order to provide a moderate performance
|
||||
* improvement without adversely affecting functional behaviour. The assembly
|
||||
* instructions generated by the IAR, ARM and GCC compilers when the respective
|
||||
* compiler's options were set for maximum optimisation has been inspected and
|
||||
* deemed to be as intended. That said, as compiler technology advances, and
|
||||
* especially if aggressive cross module optimisation is used (a use case that
|
||||
* has not been exercised to any great extend) then it is feasible that the
|
||||
* volatile qualifier will be needed for correct optimisation. It is expected
|
||||
* that a compiler removing essential code because, without the volatile
|
||||
* qualifier on the list structure members and with aggressive cross module
|
||||
* optimisation, the compiler deemed the code unnecessary will result in
|
||||
* complete and obvious failure of the scheduler. If this is ever experienced
|
||||
* then the volatile qualifier can be inserted in the relevant places within the
|
||||
* list structures by simply defining configLIST_VOLATILE to volatile in
|
||||
* FreeRTOSConfig.h (as per the example at the bottom of this comment block).
|
||||
* If configLIST_VOLATILE is not defined then the preprocessor directives below
|
||||
* will simply #define configLIST_VOLATILE away completely.
|
||||
*
|
||||
* To use volatile list structure members then add the following line to
|
||||
* FreeRTOSConfig.h (without the quotes):
|
||||
* "#define configLIST_VOLATILE volatile"
|
||||
*/
|
||||
#ifndef configLIST_VOLATILE
|
||||
#define configLIST_VOLATILE
|
||||
#endif /* configSUPPORT_CROSS_MODULE_OPTIMISATION */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Macros that can be used to place known values within the list structures,
|
||||
then check that the known values do not get corrupted during the execution of
|
||||
the application. These may catch the list data structures being overwritten in
|
||||
memory. They will not catch data errors caused by incorrect configuration or
|
||||
use of FreeRTOS.*/
|
||||
#if( configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES == 0 )
|
||||
/* Define the macros to do nothing. */
|
||||
#define listFIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE
|
||||
#define listSECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE
|
||||
#define listFIRST_LIST_INTEGRITY_CHECK_VALUE
|
||||
#define listSECOND_LIST_INTEGRITY_CHECK_VALUE
|
||||
#define listSET_FIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxItem )
|
||||
#define listSET_SECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxItem )
|
||||
#define listSET_LIST_INTEGRITY_CHECK_1_VALUE( pxList )
|
||||
#define listSET_LIST_INTEGRITY_CHECK_2_VALUE( pxList )
|
||||
#define listTEST_LIST_ITEM_INTEGRITY( pxItem )
|
||||
#define listTEST_LIST_INTEGRITY( pxList )
|
||||
#else
|
||||
/* Define macros that add new members into the list structures. */
|
||||
#define listFIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE TickType_t xListItemIntegrityValue1;
|
||||
#define listSECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE TickType_t xListItemIntegrityValue2;
|
||||
#define listFIRST_LIST_INTEGRITY_CHECK_VALUE TickType_t xListIntegrityValue1;
|
||||
#define listSECOND_LIST_INTEGRITY_CHECK_VALUE TickType_t xListIntegrityValue2;
|
||||
|
||||
/* Define macros that set the new structure members to known values. */
|
||||
#define listSET_FIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxItem ) ( pxItem )->xListItemIntegrityValue1 = pdINTEGRITY_CHECK_VALUE
|
||||
#define listSET_SECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxItem ) ( pxItem )->xListItemIntegrityValue2 = pdINTEGRITY_CHECK_VALUE
|
||||
#define listSET_LIST_INTEGRITY_CHECK_1_VALUE( pxList ) ( pxList )->xListIntegrityValue1 = pdINTEGRITY_CHECK_VALUE
|
||||
#define listSET_LIST_INTEGRITY_CHECK_2_VALUE( pxList ) ( pxList )->xListIntegrityValue2 = pdINTEGRITY_CHECK_VALUE
|
||||
|
||||
/* Define macros that will assert if one of the structure members does not
|
||||
contain its expected value. */
|
||||
#define listTEST_LIST_ITEM_INTEGRITY( pxItem ) configASSERT( ( ( pxItem )->xListItemIntegrityValue1 == pdINTEGRITY_CHECK_VALUE ) && ( ( pxItem )->xListItemIntegrityValue2 == pdINTEGRITY_CHECK_VALUE ) )
|
||||
#define listTEST_LIST_INTEGRITY( pxList ) configASSERT( ( ( pxList )->xListIntegrityValue1 == pdINTEGRITY_CHECK_VALUE ) && ( ( pxList )->xListIntegrityValue2 == pdINTEGRITY_CHECK_VALUE ) )
|
||||
#endif /* configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES */
|
||||
|
||||
|
||||
/*
|
||||
* Definition of the only type of object that a list can contain.
|
||||
*/
|
||||
struct xLIST_ITEM
|
||||
{
|
||||
listFIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE /*< Set to a known value if configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */
|
||||
configLIST_VOLATILE TickType_t xItemValue; /*< The value being listed. In most cases this is used to sort the list in descending order. */
|
||||
struct xLIST_ITEM * configLIST_VOLATILE pxNext; /*< Pointer to the next ListItem_t in the list. */
|
||||
struct xLIST_ITEM * configLIST_VOLATILE pxPrevious; /*< Pointer to the previous ListItem_t in the list. */
|
||||
void * pvOwner; /*< Pointer to the object (normally a TCB) that contains the list item. There is therefore a two way link between the object containing the list item and the list item itself. */
|
||||
void * configLIST_VOLATILE pvContainer; /*< Pointer to the list in which this list item is placed (if any). */
|
||||
listSECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE /*< Set to a known value if configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */
|
||||
};
|
||||
typedef struct xLIST_ITEM ListItem_t; /* For some reason lint wants this as two separate definitions. */
|
||||
|
||||
struct xMINI_LIST_ITEM
|
||||
{
|
||||
listFIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE /*< Set to a known value if configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */
|
||||
configLIST_VOLATILE TickType_t xItemValue;
|
||||
struct xLIST_ITEM * configLIST_VOLATILE pxNext;
|
||||
struct xLIST_ITEM * configLIST_VOLATILE pxPrevious;
|
||||
};
|
||||
typedef struct xMINI_LIST_ITEM MiniListItem_t;
|
||||
|
||||
/*
|
||||
* Definition of the type of queue used by the scheduler.
|
||||
*/
|
||||
typedef struct xLIST
|
||||
{
|
||||
listFIRST_LIST_INTEGRITY_CHECK_VALUE /*< Set to a known value if configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */
|
||||
volatile UBaseType_t uxNumberOfItems;
|
||||
ListItem_t * configLIST_VOLATILE pxIndex; /*< Used to walk through the list. Points to the last item returned by a call to listGET_OWNER_OF_NEXT_ENTRY (). */
|
||||
MiniListItem_t xListEnd; /*< List item that contains the maximum possible item value meaning it is always at the end of the list and is therefore used as a marker. */
|
||||
listSECOND_LIST_INTEGRITY_CHECK_VALUE /*< Set to a known value if configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */
|
||||
} List_t;
|
||||
|
||||
/*
|
||||
* Access macro to set the owner of a list item. The owner of a list item
|
||||
* is the object (usually a TCB) that contains the list item.
|
||||
*
|
||||
* \page listSET_LIST_ITEM_OWNER listSET_LIST_ITEM_OWNER
|
||||
* \ingroup LinkedList
|
||||
*/
|
||||
#define listSET_LIST_ITEM_OWNER( pxListItem, pxOwner ) ( ( pxListItem )->pvOwner = ( void * ) ( pxOwner ) )
|
||||
|
||||
/*
|
||||
* Access macro to get the owner of a list item. The owner of a list item
|
||||
* is the object (usually a TCB) that contains the list item.
|
||||
*
|
||||
* \page listSET_LIST_ITEM_OWNER listSET_LIST_ITEM_OWNER
|
||||
* \ingroup LinkedList
|
||||
*/
|
||||
#define listGET_LIST_ITEM_OWNER( pxListItem ) ( ( pxListItem )->pvOwner )
|
||||
|
||||
/*
|
||||
* Access macro to set the value of the list item. In most cases the value is
|
||||
* used to sort the list in descending order.
|
||||
*
|
||||
* \page listSET_LIST_ITEM_VALUE listSET_LIST_ITEM_VALUE
|
||||
* \ingroup LinkedList
|
||||
*/
|
||||
#define listSET_LIST_ITEM_VALUE( pxListItem, xValue ) ( ( pxListItem )->xItemValue = ( xValue ) )
|
||||
|
||||
/*
|
||||
* Access macro to retrieve the value of the list item. The value can
|
||||
* represent anything - for example the priority of a task, or the time at
|
||||
* which a task should be unblocked.
|
||||
*
|
||||
* \page listGET_LIST_ITEM_VALUE listGET_LIST_ITEM_VALUE
|
||||
* \ingroup LinkedList
|
||||
*/
|
||||
#define listGET_LIST_ITEM_VALUE( pxListItem ) ( ( pxListItem )->xItemValue )
|
||||
|
||||
/*
|
||||
* Access macro to retrieve the value of the list item at the head of a given
|
||||
* list.
|
||||
*
|
||||
* \page listGET_LIST_ITEM_VALUE listGET_LIST_ITEM_VALUE
|
||||
* \ingroup LinkedList
|
||||
*/
|
||||
#define listGET_ITEM_VALUE_OF_HEAD_ENTRY( pxList ) ( ( ( pxList )->xListEnd ).pxNext->xItemValue )
|
||||
|
||||
/*
|
||||
* Return the list item at the head of the list.
|
||||
*
|
||||
* \page listGET_HEAD_ENTRY listGET_HEAD_ENTRY
|
||||
* \ingroup LinkedList
|
||||
*/
|
||||
#define listGET_HEAD_ENTRY( pxList ) ( ( ( pxList )->xListEnd ).pxNext )
|
||||
|
||||
/*
|
||||
* Return the list item at the head of the list.
|
||||
*
|
||||
* \page listGET_NEXT listGET_NEXT
|
||||
* \ingroup LinkedList
|
||||
*/
|
||||
#define listGET_NEXT( pxListItem ) ( ( pxListItem )->pxNext )
|
||||
|
||||
/*
|
||||
* Return the list item that marks the end of the list
|
||||
*
|
||||
* \page listGET_END_MARKER listGET_END_MARKER
|
||||
* \ingroup LinkedList
|
||||
*/
|
||||
#define listGET_END_MARKER( pxList ) ( ( ListItem_t const * ) ( &( ( pxList )->xListEnd ) ) )
|
||||
|
||||
/*
|
||||
* Access macro to determine if a list contains any items. The macro will
|
||||
* only have the value true if the list is empty.
|
||||
*
|
||||
* \page listLIST_IS_EMPTY listLIST_IS_EMPTY
|
||||
* \ingroup LinkedList
|
||||
*/
|
||||
#define listLIST_IS_EMPTY( pxList ) ( ( BaseType_t ) ( ( pxList )->uxNumberOfItems == ( UBaseType_t ) 0 ) )
|
||||
|
||||
/*
|
||||
* Access macro to return the number of items in the list.
|
||||
*/
|
||||
#define listCURRENT_LIST_LENGTH( pxList ) ( ( pxList )->uxNumberOfItems )
|
||||
|
||||
/*
|
||||
* Access function to obtain the owner of the next entry in a list.
|
||||
*
|
||||
* The list member pxIndex is used to walk through a list. Calling
|
||||
* listGET_OWNER_OF_NEXT_ENTRY increments pxIndex to the next item in the list
|
||||
* and returns that entry's pxOwner parameter. Using multiple calls to this
|
||||
* function it is therefore possible to move through every item contained in
|
||||
* a list.
|
||||
*
|
||||
* The pxOwner parameter of a list item is a pointer to the object that owns
|
||||
* the list item. In the scheduler this is normally a task control block.
|
||||
* The pxOwner parameter effectively creates a two way link between the list
|
||||
* item and its owner.
|
||||
*
|
||||
* @param pxTCB pxTCB is set to the address of the owner of the next list item.
|
||||
* @param pxList The list from which the next item owner is to be returned.
|
||||
*
|
||||
* \page listGET_OWNER_OF_NEXT_ENTRY listGET_OWNER_OF_NEXT_ENTRY
|
||||
* \ingroup LinkedList
|
||||
*/
|
||||
#define listGET_OWNER_OF_NEXT_ENTRY( pxTCB, pxList ) \
|
||||
{ \
|
||||
List_t * const pxConstList = ( pxList ); \
|
||||
/* Increment the index to the next item and return the item, ensuring */ \
|
||||
/* we don't return the marker used at the end of the list. */ \
|
||||
( pxConstList )->pxIndex = ( pxConstList )->pxIndex->pxNext; \
|
||||
if( ( void * ) ( pxConstList )->pxIndex == ( void * ) &( ( pxConstList )->xListEnd ) ) \
|
||||
{ \
|
||||
( pxConstList )->pxIndex = ( pxConstList )->pxIndex->pxNext; \
|
||||
} \
|
||||
( pxTCB ) = ( pxConstList )->pxIndex->pvOwner; \
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Access function to obtain the owner of the first entry in a list. Lists
|
||||
* are normally sorted in ascending item value order.
|
||||
*
|
||||
* This function returns the pxOwner member of the first item in the list.
|
||||
* The pxOwner parameter of a list item is a pointer to the object that owns
|
||||
* the list item. In the scheduler this is normally a task control block.
|
||||
* The pxOwner parameter effectively creates a two way link between the list
|
||||
* item and its owner.
|
||||
*
|
||||
* @param pxList The list from which the owner of the head item is to be
|
||||
* returned.
|
||||
*
|
||||
* \page listGET_OWNER_OF_HEAD_ENTRY listGET_OWNER_OF_HEAD_ENTRY
|
||||
* \ingroup LinkedList
|
||||
*/
|
||||
#define listGET_OWNER_OF_HEAD_ENTRY( pxList ) ( (&( ( pxList )->xListEnd ))->pxNext->pvOwner )
|
||||
|
||||
/*
|
||||
* Check to see if a list item is within a list. The list item maintains a
|
||||
* "container" pointer that points to the list it is in. All this macro does
|
||||
* is check to see if the container and the list match.
|
||||
*
|
||||
* @param pxList The list we want to know if the list item is within.
|
||||
* @param pxListItem The list item we want to know if is in the list.
|
||||
* @return pdTRUE if the list item is in the list, otherwise pdFALSE.
|
||||
*/
|
||||
#define listIS_CONTAINED_WITHIN( pxList, pxListItem ) ( ( BaseType_t ) ( ( pxListItem )->pvContainer == ( void * ) ( pxList ) ) )
|
||||
|
||||
/*
|
||||
* Return the list a list item is contained within (referenced from).
|
||||
*
|
||||
* @param pxListItem The list item being queried.
|
||||
* @return A pointer to the List_t object that references the pxListItem
|
||||
*/
|
||||
#define listLIST_ITEM_CONTAINER( pxListItem ) ( ( pxListItem )->pvContainer )
|
||||
|
||||
/*
|
||||
* This provides a crude means of knowing if a list has been initialised, as
|
||||
* pxList->xListEnd.xItemValue is set to portMAX_DELAY by the vListInitialise()
|
||||
* function.
|
||||
*/
|
||||
#define listLIST_IS_INITIALISED( pxList ) ( ( pxList )->xListEnd.xItemValue == portMAX_DELAY )
|
||||
|
||||
/*
|
||||
* Must be called before a list is used! This initialises all the members
|
||||
* of the list structure and inserts the xListEnd item into the list as a
|
||||
* marker to the back of the list.
|
||||
*
|
||||
* @param pxList Pointer to the list being initialised.
|
||||
*
|
||||
* \page vListInitialise vListInitialise
|
||||
* \ingroup LinkedList
|
||||
*/
|
||||
void vListInitialise( List_t * const pxList ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/*
|
||||
* Must be called before a list item is used. This sets the list container to
|
||||
* null so the item does not think that it is already contained in a list.
|
||||
*
|
||||
* @param pxItem Pointer to the list item being initialised.
|
||||
*
|
||||
* \page vListInitialiseItem vListInitialiseItem
|
||||
* \ingroup LinkedList
|
||||
*/
|
||||
void vListInitialiseItem( ListItem_t * const pxItem ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/*
|
||||
* Insert a list item into a list. The item will be inserted into the list in
|
||||
* a position determined by its item value (descending item value order).
|
||||
*
|
||||
* @param pxList The list into which the item is to be inserted.
|
||||
*
|
||||
* @param pxNewListItem The item that is to be placed in the list.
|
||||
*
|
||||
* \page vListInsert vListInsert
|
||||
* \ingroup LinkedList
|
||||
*/
|
||||
void vListInsert( List_t * const pxList, ListItem_t * const pxNewListItem ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/*
|
||||
* Insert a list item into a list. The item will be inserted in a position
|
||||
* such that it will be the last item within the list returned by multiple
|
||||
* calls to listGET_OWNER_OF_NEXT_ENTRY.
|
||||
*
|
||||
* The list member pxIndex is used to walk through a list. Calling
|
||||
* listGET_OWNER_OF_NEXT_ENTRY increments pxIndex to the next item in the list.
|
||||
* Placing an item in a list using vListInsertEnd effectively places the item
|
||||
* in the list position pointed to by pxIndex. This means that every other
|
||||
* item within the list will be returned by listGET_OWNER_OF_NEXT_ENTRY before
|
||||
* the pxIndex parameter again points to the item being inserted.
|
||||
*
|
||||
* @param pxList The list into which the item is to be inserted.
|
||||
*
|
||||
* @param pxNewListItem The list item to be inserted into the list.
|
||||
*
|
||||
* \page vListInsertEnd vListInsertEnd
|
||||
* \ingroup LinkedList
|
||||
*/
|
||||
void vListInsertEnd( List_t * const pxList, ListItem_t * const pxNewListItem ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/*
|
||||
* Remove an item from a list. The list item has a pointer to the list that
|
||||
* it is in, so only the list item need be passed into the function.
|
||||
*
|
||||
* @param uxListRemove The item to be removed. The item will remove itself from
|
||||
* the list pointed to by it's pxContainer parameter.
|
||||
*
|
||||
* @return The number of items that remain in the list after the list item has
|
||||
* been removed.
|
||||
*
|
||||
* \page uxListRemove uxListRemove
|
||||
* \ingroup LinkedList
|
||||
*/
|
||||
UBaseType_t uxListRemove( ListItem_t * const pxItemToRemove ) PRIVILEGED_FUNCTION;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,793 +0,0 @@
|
||||
/* Copyright 2018 Canaan Inc.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* http://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.
|
||||
*/
|
||||
/*
|
||||
* FreeRTOS Kernel V10.0.1
|
||||
* Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* http://www.FreeRTOS.org
|
||||
* http://aws.amazon.com/freertos
|
||||
*
|
||||
* 1 tab == 4 spaces!
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* Message buffers build functionality on top of FreeRTOS stream buffers.
|
||||
* Whereas stream buffers are used to send a continuous stream of data from one
|
||||
* task or interrupt to another, message buffers are used to send variable
|
||||
* length discrete messages from one task or interrupt to another. Their
|
||||
* implementation is light weight, making them particularly suited for interrupt
|
||||
* to task and core to core communication scenarios.
|
||||
*
|
||||
* ***NOTE***: Uniquely among FreeRTOS objects, the stream buffer
|
||||
* implementation (so also the message buffer implementation, as message buffers
|
||||
* are built on top of stream buffers) assumes there is only one task or
|
||||
* interrupt that will write to the buffer (the writer), and only one task or
|
||||
* interrupt that will read from the buffer (the reader). It is safe for the
|
||||
* writer and reader to be different tasks or interrupts, but, unlike other
|
||||
* FreeRTOS objects, it is not safe to have multiple different writers or
|
||||
* multiple different readers. If there are to be multiple different writers
|
||||
* then the application writer must place each call to a writing API function
|
||||
* (such as xMessageBufferSend()) inside a critical section and set the send
|
||||
* block time to 0. Likewise, if there are to be multiple different readers
|
||||
* then the application writer must place each call to a reading API function
|
||||
* (such as xMessageBufferRead()) inside a critical section and set the receive
|
||||
* timeout to 0.
|
||||
*
|
||||
* Message buffers hold variable length messages. To enable that, when a
|
||||
* message is written to the message buffer an additional sizeof( size_t ) bytes
|
||||
* are also written to store the message's length (that happens internally, with
|
||||
* the API function). sizeof( size_t ) is typically 4 bytes on a 32-bit
|
||||
* architecture, so writing a 10 byte message to a message buffer on a 32-bit
|
||||
* architecture will actually reduce the available space in the message buffer
|
||||
* by 14 bytes (10 byte are used by the message, and 4 bytes to hold the length
|
||||
* of the message).
|
||||
*/
|
||||
|
||||
#ifndef FREERTOS_MESSAGE_BUFFER_H
|
||||
#define FREERTOS_MESSAGE_BUFFER_H
|
||||
|
||||
/* Message buffers are built onto of stream buffers. */
|
||||
#include "stream_buffer.h"
|
||||
|
||||
#if defined( __cplusplus )
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Type by which message buffers are referenced. For example, a call to
|
||||
* xMessageBufferCreate() returns an MessageBufferHandle_t variable that can
|
||||
* then be used as a parameter to xMessageBufferSend(), xMessageBufferReceive(),
|
||||
* etc.
|
||||
*/
|
||||
typedef void * MessageBufferHandle_t;
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* message_buffer.h
|
||||
*
|
||||
<pre>
|
||||
MessageBufferHandle_t xMessageBufferCreate( size_t xBufferSizeBytes );
|
||||
</pre>
|
||||
*
|
||||
* Creates a new message buffer using dynamically allocated memory. See
|
||||
* xMessageBufferCreateStatic() for a version that uses statically allocated
|
||||
* memory (memory that is allocated at compile time).
|
||||
*
|
||||
* configSUPPORT_DYNAMIC_ALLOCATION must be set to 1 or left undefined in
|
||||
* FreeRTOSConfig.h for xMessageBufferCreate() to be available.
|
||||
*
|
||||
* @param xBufferSizeBytes The total number of bytes (not messages) the message
|
||||
* buffer will be able to hold at any one time. When a message is written to
|
||||
* the message buffer an additional sizeof( size_t ) bytes are also written to
|
||||
* store the message's length. sizeof( size_t ) is typically 4 bytes on a
|
||||
* 32-bit architecture, so on most 32-bit architectures a 10 byte message will
|
||||
* take up 14 bytes of message buffer space.
|
||||
*
|
||||
* @return If NULL is returned, then the message buffer cannot be created
|
||||
* because there is insufficient heap memory available for FreeRTOS to allocate
|
||||
* the message buffer data structures and storage area. A non-NULL value being
|
||||
* returned indicates that the message buffer has been created successfully -
|
||||
* the returned value should be stored as the handle to the created message
|
||||
* buffer.
|
||||
*
|
||||
* Example use:
|
||||
<pre>
|
||||
|
||||
void vAFunction( void )
|
||||
{
|
||||
MessageBufferHandle_t xMessageBuffer;
|
||||
const size_t xMessageBufferSizeBytes = 100;
|
||||
|
||||
// Create a message buffer that can hold 100 bytes. The memory used to hold
|
||||
// both the message buffer structure and the messages themselves is allocated
|
||||
// dynamically. Each message added to the buffer consumes an additional 4
|
||||
// bytes which are used to hold the lengh of the message.
|
||||
xMessageBuffer = xMessageBufferCreate( xMessageBufferSizeBytes );
|
||||
|
||||
if( xMessageBuffer == NULL )
|
||||
{
|
||||
// There was not enough heap memory space available to create the
|
||||
// message buffer.
|
||||
}
|
||||
else
|
||||
{
|
||||
// The message buffer was created successfully and can now be used.
|
||||
}
|
||||
|
||||
</pre>
|
||||
* \defgroup xMessageBufferCreate xMessageBufferCreate
|
||||
* \ingroup MessageBufferManagement
|
||||
*/
|
||||
#define xMessageBufferCreate( xBufferSizeBytes ) ( MessageBufferHandle_t ) xStreamBufferGenericCreate( xBufferSizeBytes, ( size_t ) 0, pdTRUE )
|
||||
|
||||
/**
|
||||
* message_buffer.h
|
||||
*
|
||||
<pre>
|
||||
MessageBufferHandle_t xMessageBufferCreateStatic( size_t xBufferSizeBytes,
|
||||
uint8_t *pucMessageBufferStorageArea,
|
||||
StaticMessageBuffer_t *pxStaticMessageBuffer );
|
||||
</pre>
|
||||
* Creates a new message buffer using statically allocated memory. See
|
||||
* xMessageBufferCreate() for a version that uses dynamically allocated memory.
|
||||
*
|
||||
* @param xBufferSizeBytes The size, in bytes, of the buffer pointed to by the
|
||||
* pucMessageBufferStorageArea parameter. When a message is written to the
|
||||
* message buffer an additional sizeof( size_t ) bytes are also written to store
|
||||
* the message's length. sizeof( size_t ) is typically 4 bytes on a 32-bit
|
||||
* architecture, so on most 32-bit architecture a 10 byte message will take up
|
||||
* 14 bytes of message buffer space. The maximum number of bytes that can be
|
||||
* stored in the message buffer is actually (xBufferSizeBytes - 1).
|
||||
*
|
||||
* @param pucMessageBufferStorageArea Must point to a uint8_t array that is at
|
||||
* least xBufferSizeBytes + 1 big. This is the array to which messages are
|
||||
* copied when they are written to the message buffer.
|
||||
*
|
||||
* @param pxStaticMessageBuffer Must point to a variable of type
|
||||
* StaticMessageBuffer_t, which will be used to hold the message buffer's data
|
||||
* structure.
|
||||
*
|
||||
* @return If the message buffer is created successfully then a handle to the
|
||||
* created message buffer is returned. If either pucMessageBufferStorageArea or
|
||||
* pxStaticmessageBuffer are NULL then NULL is returned.
|
||||
*
|
||||
* Example use:
|
||||
<pre>
|
||||
|
||||
// Used to dimension the array used to hold the messages. The available space
|
||||
// will actually be one less than this, so 999.
|
||||
#define STORAGE_SIZE_BYTES 1000
|
||||
|
||||
// Defines the memory that will actually hold the messages within the message
|
||||
// buffer.
|
||||
static uint8_t ucStorageBuffer[ STORAGE_SIZE_BYTES ];
|
||||
|
||||
// The variable used to hold the message buffer structure.
|
||||
StaticMessageBuffer_t xMessageBufferStruct;
|
||||
|
||||
void MyFunction( void )
|
||||
{
|
||||
MessageBufferHandle_t xMessageBuffer;
|
||||
|
||||
xMessageBuffer = xMessageBufferCreateStatic( sizeof( ucBufferStorage ),
|
||||
ucBufferStorage,
|
||||
&xMessageBufferStruct );
|
||||
|
||||
// As neither the pucMessageBufferStorageArea or pxStaticMessageBuffer
|
||||
// parameters were NULL, xMessageBuffer will not be NULL, and can be used to
|
||||
// reference the created message buffer in other message buffer API calls.
|
||||
|
||||
// Other code that uses the message buffer can go here.
|
||||
}
|
||||
|
||||
</pre>
|
||||
* \defgroup xMessageBufferCreateStatic xMessageBufferCreateStatic
|
||||
* \ingroup MessageBufferManagement
|
||||
*/
|
||||
#define xMessageBufferCreateStatic( xBufferSizeBytes, pucMessageBufferStorageArea, pxStaticMessageBuffer ) ( MessageBufferHandle_t ) xStreamBufferGenericCreateStatic( xBufferSizeBytes, 0, pdTRUE, pucMessageBufferStorageArea, pxStaticMessageBuffer )
|
||||
|
||||
/**
|
||||
* message_buffer.h
|
||||
*
|
||||
<pre>
|
||||
size_t xMessageBufferSend( MessageBufferHandle_t xMessageBuffer,
|
||||
const void *pvTxData,
|
||||
size_t xDataLengthBytes,
|
||||
TickType_t xTicksToWait );
|
||||
<pre>
|
||||
*
|
||||
* Sends a discrete message to the message buffer. The message can be any
|
||||
* length that fits within the buffer's free space, and is copied into the
|
||||
* buffer.
|
||||
*
|
||||
* ***NOTE***: Uniquely among FreeRTOS objects, the stream buffer
|
||||
* implementation (so also the message buffer implementation, as message buffers
|
||||
* are built on top of stream buffers) assumes there is only one task or
|
||||
* interrupt that will write to the buffer (the writer), and only one task or
|
||||
* interrupt that will read from the buffer (the reader). It is safe for the
|
||||
* writer and reader to be different tasks or interrupts, but, unlike other
|
||||
* FreeRTOS objects, it is not safe to have multiple different writers or
|
||||
* multiple different readers. If there are to be multiple different writers
|
||||
* then the application writer must place each call to a writing API function
|
||||
* (such as xMessageBufferSend()) inside a critical section and set the send
|
||||
* block time to 0. Likewise, if there are to be multiple different readers
|
||||
* then the application writer must place each call to a reading API function
|
||||
* (such as xMessageBufferRead()) inside a critical section and set the receive
|
||||
* block time to 0.
|
||||
*
|
||||
* Use xMessageBufferSend() to write to a message buffer from a task. Use
|
||||
* xMessageBufferSendFromISR() to write to a message buffer from an interrupt
|
||||
* service routine (ISR).
|
||||
*
|
||||
* @param xMessageBuffer The handle of the message buffer to which a message is
|
||||
* being sent.
|
||||
*
|
||||
* @param pvTxData A pointer to the message that is to be copied into the
|
||||
* message buffer.
|
||||
*
|
||||
* @param xDataLengthBytes The length of the message. That is, the number of
|
||||
* bytes to copy from pvTxData into the message buffer. When a message is
|
||||
* written to the message buffer an additional sizeof( size_t ) bytes are also
|
||||
* written to store the message's length. sizeof( size_t ) is typically 4 bytes
|
||||
* on a 32-bit architecture, so on most 32-bit architecture setting
|
||||
* xDataLengthBytes to 20 will reduce the free space in the message buffer by 24
|
||||
* bytes (20 bytes of message data and 4 bytes to hold the message length).
|
||||
*
|
||||
* @param xTicksToWait The maximum amount of time the calling task should remain
|
||||
* in the Blocked state to wait for enough space to become available in the
|
||||
* message buffer, should the message buffer have insufficient space when
|
||||
* xMessageBufferSend() is called. The calling task will never block if
|
||||
* xTicksToWait is zero. The block time is specified in tick periods, so the
|
||||
* absolute time it represents is dependent on the tick frequency. The macro
|
||||
* pdMS_TO_TICKS() can be used to convert a time specified in milliseconds into
|
||||
* a time specified in ticks. Setting xTicksToWait to portMAX_DELAY will cause
|
||||
* the task to wait indefinitely (without timing out), provided
|
||||
* INCLUDE_vTaskSuspend is set to 1 in FreeRTOSConfig.h. Tasks do not use any
|
||||
* CPU time when they are in the Blocked state.
|
||||
*
|
||||
* @return The number of bytes written to the message buffer. If the call to
|
||||
* xMessageBufferSend() times out before there was enough space to write the
|
||||
* message into the message buffer then zero is returned. If the call did not
|
||||
* time out then xDataLengthBytes is returned.
|
||||
*
|
||||
* Example use:
|
||||
<pre>
|
||||
void vAFunction( MessageBufferHandle_t xMessageBuffer )
|
||||
{
|
||||
size_t xBytesSent;
|
||||
uint8_t ucArrayToSend[] = { 0, 1, 2, 3 };
|
||||
char *pcStringToSend = "String to send";
|
||||
const TickType_t x100ms = pdMS_TO_TICKS( 100 );
|
||||
|
||||
// Send an array to the message buffer, blocking for a maximum of 100ms to
|
||||
// wait for enough space to be available in the message buffer.
|
||||
xBytesSent = xMessageBufferSend( xMessageBuffer, ( void * ) ucArrayToSend, sizeof( ucArrayToSend ), x100ms );
|
||||
|
||||
if( xBytesSent != sizeof( ucArrayToSend ) )
|
||||
{
|
||||
// The call to xMessageBufferSend() times out before there was enough
|
||||
// space in the buffer for the data to be written.
|
||||
}
|
||||
|
||||
// Send the string to the message buffer. Return immediately if there is
|
||||
// not enough space in the buffer.
|
||||
xBytesSent = xMessageBufferSend( xMessageBuffer, ( void * ) pcStringToSend, strlen( pcStringToSend ), 0 );
|
||||
|
||||
if( xBytesSent != strlen( pcStringToSend ) )
|
||||
{
|
||||
// The string could not be added to the message buffer because there was
|
||||
// not enough free space in the buffer.
|
||||
}
|
||||
}
|
||||
</pre>
|
||||
* \defgroup xMessageBufferSend xMessageBufferSend
|
||||
* \ingroup MessageBufferManagement
|
||||
*/
|
||||
#define xMessageBufferSend( xMessageBuffer, pvTxData, xDataLengthBytes, xTicksToWait ) xStreamBufferSend( ( StreamBufferHandle_t ) xMessageBuffer, pvTxData, xDataLengthBytes, xTicksToWait )
|
||||
|
||||
/**
|
||||
* message_buffer.h
|
||||
*
|
||||
<pre>
|
||||
size_t xMessageBufferSendFromISR( MessageBufferHandle_t xMessageBuffer,
|
||||
const void *pvTxData,
|
||||
size_t xDataLengthBytes,
|
||||
BaseType_t *pxHigherPriorityTaskWoken );
|
||||
<pre>
|
||||
*
|
||||
* Interrupt safe version of the API function that sends a discrete message to
|
||||
* the message buffer. The message can be any length that fits within the
|
||||
* buffer's free space, and is copied into the buffer.
|
||||
*
|
||||
* ***NOTE***: Uniquely among FreeRTOS objects, the stream buffer
|
||||
* implementation (so also the message buffer implementation, as message buffers
|
||||
* are built on top of stream buffers) assumes there is only one task or
|
||||
* interrupt that will write to the buffer (the writer), and only one task or
|
||||
* interrupt that will read from the buffer (the reader). It is safe for the
|
||||
* writer and reader to be different tasks or interrupts, but, unlike other
|
||||
* FreeRTOS objects, it is not safe to have multiple different writers or
|
||||
* multiple different readers. If there are to be multiple different writers
|
||||
* then the application writer must place each call to a writing API function
|
||||
* (such as xMessageBufferSend()) inside a critical section and set the send
|
||||
* block time to 0. Likewise, if there are to be multiple different readers
|
||||
* then the application writer must place each call to a reading API function
|
||||
* (such as xMessageBufferRead()) inside a critical section and set the receive
|
||||
* block time to 0.
|
||||
*
|
||||
* Use xMessageBufferSend() to write to a message buffer from a task. Use
|
||||
* xMessageBufferSendFromISR() to write to a message buffer from an interrupt
|
||||
* service routine (ISR).
|
||||
*
|
||||
* @param xMessageBuffer The handle of the message buffer to which a message is
|
||||
* being sent.
|
||||
*
|
||||
* @param pvTxData A pointer to the message that is to be copied into the
|
||||
* message buffer.
|
||||
*
|
||||
* @param xDataLengthBytes The length of the message. That is, the number of
|
||||
* bytes to copy from pvTxData into the message buffer. When a message is
|
||||
* written to the message buffer an additional sizeof( size_t ) bytes are also
|
||||
* written to store the message's length. sizeof( size_t ) is typically 4 bytes
|
||||
* on a 32-bit architecture, so on most 32-bit architecture setting
|
||||
* xDataLengthBytes to 20 will reduce the free space in the message buffer by 24
|
||||
* bytes (20 bytes of message data and 4 bytes to hold the message length).
|
||||
*
|
||||
* @param pxHigherPriorityTaskWoken It is possible that a message buffer will
|
||||
* have a task blocked on it waiting for data. Calling
|
||||
* xMessageBufferSendFromISR() can make data available, and so cause a task that
|
||||
* was waiting for data to leave the Blocked state. If calling
|
||||
* xMessageBufferSendFromISR() causes a task to leave the Blocked state, and the
|
||||
* unblocked task has a priority higher than the currently executing task (the
|
||||
* task that was interrupted), then, internally, xMessageBufferSendFromISR()
|
||||
* will set *pxHigherPriorityTaskWoken to pdTRUE. If
|
||||
* xMessageBufferSendFromISR() sets this value to pdTRUE, then normally a
|
||||
* context switch should be performed before the interrupt is exited. This will
|
||||
* ensure that the interrupt returns directly to the highest priority Ready
|
||||
* state task. *pxHigherPriorityTaskWoken should be set to pdFALSE before it
|
||||
* is passed into the function. See the code example below for an example.
|
||||
*
|
||||
* @return The number of bytes actually written to the message buffer. If the
|
||||
* message buffer didn't have enough free space for the message to be stored
|
||||
* then 0 is returned, otherwise xDataLengthBytes is returned.
|
||||
*
|
||||
* Example use:
|
||||
<pre>
|
||||
// A message buffer that has already been created.
|
||||
MessageBufferHandle_t xMessageBuffer;
|
||||
|
||||
void vAnInterruptServiceRoutine( void )
|
||||
{
|
||||
size_t xBytesSent;
|
||||
char *pcStringToSend = "String to send";
|
||||
BaseType_t xHigherPriorityTaskWoken = pdFALSE; // Initialised to pdFALSE.
|
||||
|
||||
// Attempt to send the string to the message buffer.
|
||||
xBytesSent = xMessageBufferSendFromISR( xMessageBuffer,
|
||||
( void * ) pcStringToSend,
|
||||
strlen( pcStringToSend ),
|
||||
&xHigherPriorityTaskWoken );
|
||||
|
||||
if( xBytesSent != strlen( pcStringToSend ) )
|
||||
{
|
||||
// The string could not be added to the message buffer because there was
|
||||
// not enough free space in the buffer.
|
||||
}
|
||||
|
||||
// If xHigherPriorityTaskWoken was set to pdTRUE inside
|
||||
// xMessageBufferSendFromISR() then a task that has a priority above the
|
||||
// priority of the currently executing task was unblocked and a context
|
||||
// switch should be performed to ensure the ISR returns to the unblocked
|
||||
// task. In most FreeRTOS ports this is done by simply passing
|
||||
// xHigherPriorityTaskWoken into taskYIELD_FROM_ISR(), which will test the
|
||||
// variables value, and perform the context switch if necessary. Check the
|
||||
// documentation for the port in use for port specific instructions.
|
||||
taskYIELD_FROM_ISR( xHigherPriorityTaskWoken );
|
||||
}
|
||||
</pre>
|
||||
* \defgroup xMessageBufferSendFromISR xMessageBufferSendFromISR
|
||||
* \ingroup MessageBufferManagement
|
||||
*/
|
||||
#define xMessageBufferSendFromISR( xMessageBuffer, pvTxData, xDataLengthBytes, pxHigherPriorityTaskWoken ) xStreamBufferSendFromISR( ( StreamBufferHandle_t ) xMessageBuffer, pvTxData, xDataLengthBytes, pxHigherPriorityTaskWoken )
|
||||
|
||||
/**
|
||||
* message_buffer.h
|
||||
*
|
||||
<pre>
|
||||
size_t xMessageBufferReceive( MessageBufferHandle_t xMessageBuffer,
|
||||
void *pvRxData,
|
||||
size_t xBufferLengthBytes,
|
||||
TickType_t xTicksToWait );
|
||||
</pre>
|
||||
*
|
||||
* Receives a discrete message from a message buffer. Messages can be of
|
||||
* variable length and are copied out of the buffer.
|
||||
*
|
||||
* ***NOTE***: Uniquely among FreeRTOS objects, the stream buffer
|
||||
* implementation (so also the message buffer implementation, as message buffers
|
||||
* are built on top of stream buffers) assumes there is only one task or
|
||||
* interrupt that will write to the buffer (the writer), and only one task or
|
||||
* interrupt that will read from the buffer (the reader). It is safe for the
|
||||
* writer and reader to be different tasks or interrupts, but, unlike other
|
||||
* FreeRTOS objects, it is not safe to have multiple different writers or
|
||||
* multiple different readers. If there are to be multiple different writers
|
||||
* then the application writer must place each call to a writing API function
|
||||
* (such as xMessageBufferSend()) inside a critical section and set the send
|
||||
* block time to 0. Likewise, if there are to be multiple different readers
|
||||
* then the application writer must place each call to a reading API function
|
||||
* (such as xMessageBufferRead()) inside a critical section and set the receive
|
||||
* block time to 0.
|
||||
*
|
||||
* Use xMessageBufferReceive() to read from a message buffer from a task. Use
|
||||
* xMessageBufferReceiveFromISR() to read from a message buffer from an
|
||||
* interrupt service routine (ISR).
|
||||
*
|
||||
* @param xMessageBuffer The handle of the message buffer from which a message
|
||||
* is being received.
|
||||
*
|
||||
* @param pvRxData A pointer to the buffer into which the received message is
|
||||
* to be copied.
|
||||
*
|
||||
* @param xBufferLengthBytes The length of the buffer pointed to by the pvRxData
|
||||
* parameter. This sets the maximum length of the message that can be received.
|
||||
* If xBufferLengthBytes is too small to hold the next message then the message
|
||||
* will be left in the message buffer and 0 will be returned.
|
||||
*
|
||||
* @param xTicksToWait The maximum amount of time the task should remain in the
|
||||
* Blocked state to wait for a message, should the message buffer be empty.
|
||||
* xMessageBufferReceive() will return immediately if xTicksToWait is zero and
|
||||
* the message buffer is empty. The block time is specified in tick periods, so
|
||||
* the absolute time it represents is dependent on the tick frequency. The
|
||||
* macro pdMS_TO_TICKS() can be used to convert a time specified in milliseconds
|
||||
* into a time specified in ticks. Setting xTicksToWait to portMAX_DELAY will
|
||||
* cause the task to wait indefinitely (without timing out), provided
|
||||
* INCLUDE_vTaskSuspend is set to 1 in FreeRTOSConfig.h. Tasks do not use any
|
||||
* CPU time when they are in the Blocked state.
|
||||
*
|
||||
* @return The length, in bytes, of the message read from the message buffer, if
|
||||
* any. If xMessageBufferReceive() times out before a message became available
|
||||
* then zero is returned. If the length of the message is greater than
|
||||
* xBufferLengthBytes then the message will be left in the message buffer and
|
||||
* zero is returned.
|
||||
*
|
||||
* Example use:
|
||||
<pre>
|
||||
void vAFunction( MessageBuffer_t xMessageBuffer )
|
||||
{
|
||||
uint8_t ucRxData[ 20 ];
|
||||
size_t xReceivedBytes;
|
||||
const TickType_t xBlockTime = pdMS_TO_TICKS( 20 );
|
||||
|
||||
// Receive the next message from the message buffer. Wait in the Blocked
|
||||
// state (so not using any CPU processing time) for a maximum of 100ms for
|
||||
// a message to become available.
|
||||
xReceivedBytes = xMessageBufferReceive( xMessageBuffer,
|
||||
( void * ) ucRxData,
|
||||
sizeof( ucRxData ),
|
||||
xBlockTime );
|
||||
|
||||
if( xReceivedBytes > 0 )
|
||||
{
|
||||
// A ucRxData contains a message that is xReceivedBytes long. Process
|
||||
// the message here....
|
||||
}
|
||||
}
|
||||
</pre>
|
||||
* \defgroup xMessageBufferReceive xMessageBufferReceive
|
||||
* \ingroup MessageBufferManagement
|
||||
*/
|
||||
#define xMessageBufferReceive( xMessageBuffer, pvRxData, xBufferLengthBytes, xTicksToWait ) xStreamBufferReceive( ( StreamBufferHandle_t ) xMessageBuffer, pvRxData, xBufferLengthBytes, xTicksToWait )
|
||||
|
||||
|
||||
/**
|
||||
* message_buffer.h
|
||||
*
|
||||
<pre>
|
||||
size_t xMessageBufferReceiveFromISR( MessageBufferHandle_t xMessageBuffer,
|
||||
void *pvRxData,
|
||||
size_t xBufferLengthBytes,
|
||||
BaseType_t *pxHigherPriorityTaskWoken );
|
||||
</pre>
|
||||
*
|
||||
* An interrupt safe version of the API function that receives a discrete
|
||||
* message from a message buffer. Messages can be of variable length and are
|
||||
* copied out of the buffer.
|
||||
*
|
||||
* ***NOTE***: Uniquely among FreeRTOS objects, the stream buffer
|
||||
* implementation (so also the message buffer implementation, as message buffers
|
||||
* are built on top of stream buffers) assumes there is only one task or
|
||||
* interrupt that will write to the buffer (the writer), and only one task or
|
||||
* interrupt that will read from the buffer (the reader). It is safe for the
|
||||
* writer and reader to be different tasks or interrupts, but, unlike other
|
||||
* FreeRTOS objects, it is not safe to have multiple different writers or
|
||||
* multiple different readers. If there are to be multiple different writers
|
||||
* then the application writer must place each call to a writing API function
|
||||
* (such as xMessageBufferSend()) inside a critical section and set the send
|
||||
* block time to 0. Likewise, if there are to be multiple different readers
|
||||
* then the application writer must place each call to a reading API function
|
||||
* (such as xMessageBufferRead()) inside a critical section and set the receive
|
||||
* block time to 0.
|
||||
*
|
||||
* Use xMessageBufferReceive() to read from a message buffer from a task. Use
|
||||
* xMessageBufferReceiveFromISR() to read from a message buffer from an
|
||||
* interrupt service routine (ISR).
|
||||
*
|
||||
* @param xMessageBuffer The handle of the message buffer from which a message
|
||||
* is being received.
|
||||
*
|
||||
* @param pvRxData A pointer to the buffer into which the received message is
|
||||
* to be copied.
|
||||
*
|
||||
* @param xBufferLengthBytes The length of the buffer pointed to by the pvRxData
|
||||
* parameter. This sets the maximum length of the message that can be received.
|
||||
* If xBufferLengthBytes is too small to hold the next message then the message
|
||||
* will be left in the message buffer and 0 will be returned.
|
||||
*
|
||||
* @param pxHigherPriorityTaskWoken It is possible that a message buffer will
|
||||
* have a task blocked on it waiting for space to become available. Calling
|
||||
* xMessageBufferReceiveFromISR() can make space available, and so cause a task
|
||||
* that is waiting for space to leave the Blocked state. If calling
|
||||
* xMessageBufferReceiveFromISR() causes a task to leave the Blocked state, and
|
||||
* the unblocked task has a priority higher than the currently executing task
|
||||
* (the task that was interrupted), then, internally,
|
||||
* xMessageBufferReceiveFromISR() will set *pxHigherPriorityTaskWoken to pdTRUE.
|
||||
* If xMessageBufferReceiveFromISR() sets this value to pdTRUE, then normally a
|
||||
* context switch should be performed before the interrupt is exited. That will
|
||||
* ensure the interrupt returns directly to the highest priority Ready state
|
||||
* task. *pxHigherPriorityTaskWoken should be set to pdFALSE before it is
|
||||
* passed into the function. See the code example below for an example.
|
||||
*
|
||||
* @return The length, in bytes, of the message read from the message buffer, if
|
||||
* any.
|
||||
*
|
||||
* Example use:
|
||||
<pre>
|
||||
// A message buffer that has already been created.
|
||||
MessageBuffer_t xMessageBuffer;
|
||||
|
||||
void vAnInterruptServiceRoutine( void )
|
||||
{
|
||||
uint8_t ucRxData[ 20 ];
|
||||
size_t xReceivedBytes;
|
||||
BaseType_t xHigherPriorityTaskWoken = pdFALSE; // Initialised to pdFALSE.
|
||||
|
||||
// Receive the next message from the message buffer.
|
||||
xReceivedBytes = xMessageBufferReceiveFromISR( xMessageBuffer,
|
||||
( void * ) ucRxData,
|
||||
sizeof( ucRxData ),
|
||||
&xHigherPriorityTaskWoken );
|
||||
|
||||
if( xReceivedBytes > 0 )
|
||||
{
|
||||
// A ucRxData contains a message that is xReceivedBytes long. Process
|
||||
// the message here....
|
||||
}
|
||||
|
||||
// If xHigherPriorityTaskWoken was set to pdTRUE inside
|
||||
// xMessageBufferReceiveFromISR() then a task that has a priority above the
|
||||
// priority of the currently executing task was unblocked and a context
|
||||
// switch should be performed to ensure the ISR returns to the unblocked
|
||||
// task. In most FreeRTOS ports this is done by simply passing
|
||||
// xHigherPriorityTaskWoken into taskYIELD_FROM_ISR(), which will test the
|
||||
// variables value, and perform the context switch if necessary. Check the
|
||||
// documentation for the port in use for port specific instructions.
|
||||
taskYIELD_FROM_ISR( xHigherPriorityTaskWoken );
|
||||
}
|
||||
</pre>
|
||||
* \defgroup xMessageBufferReceiveFromISR xMessageBufferReceiveFromISR
|
||||
* \ingroup MessageBufferManagement
|
||||
*/
|
||||
#define xMessageBufferReceiveFromISR( xMessageBuffer, pvRxData, xBufferLengthBytes, pxHigherPriorityTaskWoken ) xStreamBufferReceiveFromISR( ( StreamBufferHandle_t ) xMessageBuffer, pvRxData, xBufferLengthBytes, pxHigherPriorityTaskWoken )
|
||||
|
||||
/**
|
||||
* message_buffer.h
|
||||
*
|
||||
<pre>
|
||||
void vMessageBufferDelete( MessageBufferHandle_t xMessageBuffer );
|
||||
</pre>
|
||||
*
|
||||
* Deletes a message buffer that was previously created using a call to
|
||||
* xMessageBufferCreate() or xMessageBufferCreateStatic(). If the message
|
||||
* buffer was created using dynamic memory (that is, by xMessageBufferCreate()),
|
||||
* then the allocated memory is freed.
|
||||
*
|
||||
* A message buffer handle must not be used after the message buffer has been
|
||||
* deleted.
|
||||
*
|
||||
* @param xMessageBuffer The handle of the message buffer to be deleted.
|
||||
*
|
||||
*/
|
||||
#define vMessageBufferDelete( xMessageBuffer ) vStreamBufferDelete( ( StreamBufferHandle_t ) xMessageBuffer )
|
||||
|
||||
/**
|
||||
* message_buffer.h
|
||||
<pre>
|
||||
BaseType_t xMessageBufferIsFull( MessageBufferHandle_t xMessageBuffer ) );
|
||||
</pre>
|
||||
*
|
||||
* Tests to see if a message buffer is full. A message buffer is full if it
|
||||
* cannot accept any more messages, of any size, until space is made available
|
||||
* by a message being removed from the message buffer.
|
||||
*
|
||||
* @param xMessageBuffer The handle of the message buffer being queried.
|
||||
*
|
||||
* @return If the message buffer referenced by xMessageBuffer is full then
|
||||
* pdTRUE is returned. Otherwise pdFALSE is returned.
|
||||
*/
|
||||
#define xMessageBufferIsFull( xMessageBuffer ) xStreamBufferIsFull( ( StreamBufferHandle_t ) xMessageBuffer )
|
||||
|
||||
/**
|
||||
* message_buffer.h
|
||||
<pre>
|
||||
BaseType_t xMessageBufferIsEmpty( MessageBufferHandle_t xMessageBuffer ) );
|
||||
</pre>
|
||||
*
|
||||
* Tests to see if a message buffer is empty (does not contain any messages).
|
||||
*
|
||||
* @param xMessageBuffer The handle of the message buffer being queried.
|
||||
*
|
||||
* @return If the message buffer referenced by xMessageBuffer is empty then
|
||||
* pdTRUE is returned. Otherwise pdFALSE is returned.
|
||||
*
|
||||
*/
|
||||
#define xMessageBufferIsEmpty( xMessageBuffer ) xStreamBufferIsEmpty( ( StreamBufferHandle_t ) xMessageBuffer )
|
||||
|
||||
/**
|
||||
* message_buffer.h
|
||||
<pre>
|
||||
BaseType_t xMessageBufferReset( MessageBufferHandle_t xMessageBuffer );
|
||||
</pre>
|
||||
*
|
||||
* Resets a message buffer to its initial empty state, discarding any message it
|
||||
* contained.
|
||||
*
|
||||
* A message buffer can only be reset if there are no tasks blocked on it.
|
||||
*
|
||||
* @param xMessageBuffer The handle of the message buffer being reset.
|
||||
*
|
||||
* @return If the message buffer was reset then pdPASS is returned. If the
|
||||
* message buffer could not be reset because either there was a task blocked on
|
||||
* the message queue to wait for space to become available, or to wait for a
|
||||
* a message to be available, then pdFAIL is returned.
|
||||
*
|
||||
* \defgroup xMessageBufferReset xMessageBufferReset
|
||||
* \ingroup MessageBufferManagement
|
||||
*/
|
||||
#define xMessageBufferReset( xMessageBuffer ) xStreamBufferReset( ( StreamBufferHandle_t ) xMessageBuffer )
|
||||
|
||||
|
||||
/**
|
||||
* message_buffer.h
|
||||
<pre>
|
||||
size_t xMessageBufferSpaceAvailable( MessageBufferHandle_t xMessageBuffer ) );
|
||||
</pre>
|
||||
* Returns the number of bytes of free space in the message buffer.
|
||||
*
|
||||
* @param xMessageBuffer The handle of the message buffer being queried.
|
||||
*
|
||||
* @return The number of bytes that can be written to the message buffer before
|
||||
* the message buffer would be full. When a message is written to the message
|
||||
* buffer an additional sizeof( size_t ) bytes are also written to store the
|
||||
* message's length. sizeof( size_t ) is typically 4 bytes on a 32-bit
|
||||
* architecture, so if xMessageBufferSpacesAvailable() returns 10, then the size
|
||||
* of the largest message that can be written to the message buffer is 6 bytes.
|
||||
*
|
||||
* \defgroup xMessageBufferSpaceAvailable xMessageBufferSpaceAvailable
|
||||
* \ingroup MessageBufferManagement
|
||||
*/
|
||||
#define xMessageBufferSpaceAvailable( xMessageBuffer ) xStreamBufferSpacesAvailable( ( StreamBufferHandle_t ) xMessageBuffer )
|
||||
|
||||
/**
|
||||
* message_buffer.h
|
||||
*
|
||||
<pre>
|
||||
BaseType_t xMessageBufferSendCompletedFromISR( MessageBufferHandle_t xStreamBuffer, BaseType_t *pxHigherPriorityTaskWoken );
|
||||
</pre>
|
||||
*
|
||||
* For advanced users only.
|
||||
*
|
||||
* The sbSEND_COMPLETED() macro is called from within the FreeRTOS APIs when
|
||||
* data is sent to a message buffer or stream buffer. If there was a task that
|
||||
* was blocked on the message or stream buffer waiting for data to arrive then
|
||||
* the sbSEND_COMPLETED() macro sends a notification to the task to remove it
|
||||
* from the Blocked state. xMessageBufferSendCompletedFromISR() does the same
|
||||
* thing. It is provided to enable application writers to implement their own
|
||||
* version of sbSEND_COMPLETED(), and MUST NOT BE USED AT ANY OTHER TIME.
|
||||
*
|
||||
* See the example implemented in FreeRTOS/Demo/Minimal/MessageBufferAMP.c for
|
||||
* additional information.
|
||||
*
|
||||
* @param xStreamBuffer The handle of the stream buffer to which data was
|
||||
* written.
|
||||
*
|
||||
* @param pxHigherPriorityTaskWoken *pxHigherPriorityTaskWoken should be
|
||||
* initialised to pdFALSE before it is passed into
|
||||
* xMessageBufferSendCompletedFromISR(). If calling
|
||||
* xMessageBufferSendCompletedFromISR() removes a task from the Blocked state,
|
||||
* and the task has a priority above the priority of the currently running task,
|
||||
* then *pxHigherPriorityTaskWoken will get set to pdTRUE indicating that a
|
||||
* context switch should be performed before exiting the ISR.
|
||||
*
|
||||
* @return If a task was removed from the Blocked state then pdTRUE is returned.
|
||||
* Otherwise pdFALSE is returned.
|
||||
*
|
||||
* \defgroup xMessageBufferSendCompletedFromISR xMessageBufferSendCompletedFromISR
|
||||
* \ingroup StreamBufferManagement
|
||||
*/
|
||||
#define xMessageBufferSendCompletedFromISR( xMessageBuffer, pxHigherPriorityTaskWoken ) xStreamBufferSendCompletedFromISR( ( StreamBufferHandle_t ) xMessageBuffer, pxHigherPriorityTaskWoken )
|
||||
|
||||
/**
|
||||
* message_buffer.h
|
||||
*
|
||||
<pre>
|
||||
BaseType_t xMessageBufferReceiveCompletedFromISR( MessageBufferHandle_t xStreamBuffer, BaseType_t *pxHigherPriorityTaskWoken );
|
||||
</pre>
|
||||
*
|
||||
* For advanced users only.
|
||||
*
|
||||
* The sbRECEIVE_COMPLETED() macro is called from within the FreeRTOS APIs when
|
||||
* data is read out of a message buffer or stream buffer. If there was a task
|
||||
* that was blocked on the message or stream buffer waiting for data to arrive
|
||||
* then the sbRECEIVE_COMPLETED() macro sends a notification to the task to
|
||||
* remove it from the Blocked state. xMessageBufferReceiveCompletedFromISR()
|
||||
* does the same thing. It is provided to enable application writers to
|
||||
* implement their own version of sbRECEIVE_COMPLETED(), and MUST NOT BE USED AT
|
||||
* ANY OTHER TIME.
|
||||
*
|
||||
* See the example implemented in FreeRTOS/Demo/Minimal/MessageBufferAMP.c for
|
||||
* additional information.
|
||||
*
|
||||
* @param xStreamBuffer The handle of the stream buffer from which data was
|
||||
* read.
|
||||
*
|
||||
* @param pxHigherPriorityTaskWoken *pxHigherPriorityTaskWoken should be
|
||||
* initialised to pdFALSE before it is passed into
|
||||
* xMessageBufferReceiveCompletedFromISR(). If calling
|
||||
* xMessageBufferReceiveCompletedFromISR() removes a task from the Blocked state,
|
||||
* and the task has a priority above the priority of the currently running task,
|
||||
* then *pxHigherPriorityTaskWoken will get set to pdTRUE indicating that a
|
||||
* context switch should be performed before exiting the ISR.
|
||||
*
|
||||
* @return If a task was removed from the Blocked state then pdTRUE is returned.
|
||||
* Otherwise pdFALSE is returned.
|
||||
*
|
||||
* \defgroup xMessageBufferReceiveCompletedFromISR xMessageBufferReceiveCompletedFromISR
|
||||
* \ingroup StreamBufferManagement
|
||||
*/
|
||||
#define xMessageBufferReceiveCompletedFromISR( xMessageBuffer, pxHigherPriorityTaskWoken ) xStreamBufferReceiveCompletedFromISR( ( StreamBufferHandle_t ) xMessageBuffer, pxHigherPriorityTaskWoken )
|
||||
|
||||
#if defined( __cplusplus )
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /* !defined( FREERTOS_MESSAGE_BUFFER_H ) */
|
||||
@@ -1,169 +0,0 @@
|
||||
/* Copyright 2018 Canaan Inc.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* http://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.
|
||||
*/
|
||||
/*
|
||||
* FreeRTOS Kernel V10.0.1
|
||||
* Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* http://www.FreeRTOS.org
|
||||
* http://aws.amazon.com/freertos
|
||||
*
|
||||
* 1 tab == 4 spaces!
|
||||
*/
|
||||
|
||||
/*
|
||||
* When the MPU is used the standard (non MPU) API functions are mapped to
|
||||
* equivalents that start "MPU_", the prototypes for which are defined in this
|
||||
* header files. This will cause the application code to call the MPU_ version
|
||||
* which wraps the non-MPU version with privilege promoting then demoting code,
|
||||
* so the kernel code always runs will full privileges.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef MPU_PROTOTYPES_H
|
||||
#define MPU_PROTOTYPES_H
|
||||
|
||||
/* MPU versions of tasks.h API functions. */
|
||||
BaseType_t MPU_xTaskCreate( TaskFunction_t pxTaskCode, const char * const pcName, const uint16_t usStackDepth, void * const pvParameters, UBaseType_t uxPriority, TaskHandle_t * const pxCreatedTask );
|
||||
TaskHandle_t MPU_xTaskCreateStatic( TaskFunction_t pxTaskCode, const char * const pcName, const uint32_t ulStackDepth, void * const pvParameters, UBaseType_t uxPriority, StackType_t * const puxStackBuffer, StaticTask_t * const pxTaskBuffer );
|
||||
BaseType_t MPU_xTaskCreateRestricted( const TaskParameters_t * const pxTaskDefinition, TaskHandle_t *pxCreatedTask );
|
||||
BaseType_t MPU_xTaskCreateRestrictedStatic( const TaskParameters_t * const pxTaskDefinition, TaskHandle_t *pxCreatedTask );
|
||||
void MPU_vTaskAllocateMPURegions( TaskHandle_t xTask, const MemoryRegion_t * const pxRegions );
|
||||
void MPU_vTaskDelete( TaskHandle_t xTaskToDelete );
|
||||
void MPU_vTaskDelay( const TickType_t xTicksToDelay );
|
||||
void MPU_vTaskDelayUntil( TickType_t * const pxPreviousWakeTime, const TickType_t xTimeIncrement );
|
||||
BaseType_t MPU_xTaskAbortDelay( TaskHandle_t xTask );
|
||||
UBaseType_t MPU_uxTaskPriorityGet( TaskHandle_t xTask );
|
||||
eTaskState MPU_eTaskGetState( TaskHandle_t xTask );
|
||||
void MPU_vTaskGetInfo( TaskHandle_t xTask, TaskStatus_t *pxTaskStatus, BaseType_t xGetFreeStackSpace, eTaskState eState );
|
||||
void MPU_vTaskPrioritySet( TaskHandle_t xTask, UBaseType_t uxNewPriority );
|
||||
void MPU_vTaskSuspend( TaskHandle_t xTaskToSuspend );
|
||||
void MPU_vTaskResume( TaskHandle_t xTaskToResume );
|
||||
void MPU_vTaskStartScheduler( void );
|
||||
void MPU_vTaskSuspendAll( void );
|
||||
BaseType_t MPU_xTaskResumeAll( void );
|
||||
TickType_t MPU_xTaskGetTickCount( void );
|
||||
UBaseType_t MPU_uxTaskGetNumberOfTasks( void );
|
||||
char * MPU_pcTaskGetName( TaskHandle_t xTaskToQuery );
|
||||
TaskHandle_t MPU_xTaskGetHandle( const char *pcNameToQuery );
|
||||
UBaseType_t MPU_uxTaskGetStackHighWaterMark( TaskHandle_t xTask );
|
||||
void MPU_vTaskSetApplicationTaskTag( TaskHandle_t xTask, TaskHookFunction_t pxHookFunction );
|
||||
TaskHookFunction_t MPU_xTaskGetApplicationTaskTag( TaskHandle_t xTask );
|
||||
void MPU_vTaskSetThreadLocalStoragePointer( TaskHandle_t xTaskToSet, BaseType_t xIndex, void *pvValue );
|
||||
void * MPU_pvTaskGetThreadLocalStoragePointer( TaskHandle_t xTaskToQuery, BaseType_t xIndex );
|
||||
BaseType_t MPU_xTaskCallApplicationTaskHook( TaskHandle_t xTask, void *pvParameter );
|
||||
TaskHandle_t MPU_xTaskGetIdleTaskHandle( void );
|
||||
UBaseType_t MPU_uxTaskGetSystemState( TaskStatus_t * const pxTaskStatusArray, const UBaseType_t uxArraySize, uint32_t * const pulTotalRunTime );
|
||||
void MPU_vTaskList( char * pcWriteBuffer );
|
||||
void MPU_vTaskGetRunTimeStats( char *pcWriteBuffer );
|
||||
BaseType_t MPU_xTaskGenericNotify( TaskHandle_t xTaskToNotify, uint32_t ulValue, eNotifyAction eAction, uint32_t *pulPreviousNotificationValue );
|
||||
BaseType_t MPU_xTaskNotifyWait( uint32_t ulBitsToClearOnEntry, uint32_t ulBitsToClearOnExit, uint32_t *pulNotificationValue, TickType_t xTicksToWait );
|
||||
uint32_t MPU_ulTaskNotifyTake( BaseType_t xClearCountOnExit, TickType_t xTicksToWait );
|
||||
BaseType_t MPU_xTaskNotifyStateClear( TaskHandle_t xTask );
|
||||
BaseType_t MPU_xTaskIncrementTick( void );
|
||||
TaskHandle_t MPU_xTaskGetCurrentTaskHandle( void );
|
||||
void MPU_vTaskSetTimeOutState( TimeOut_t * const pxTimeOut );
|
||||
BaseType_t MPU_xTaskCheckForTimeOut( TimeOut_t * const pxTimeOut, TickType_t * const pxTicksToWait );
|
||||
void MPU_vTaskMissedYield( void );
|
||||
BaseType_t MPU_xTaskGetSchedulerState( void );
|
||||
|
||||
/* MPU versions of queue.h API functions. */
|
||||
BaseType_t MPU_xQueueGenericSend( QueueHandle_t xQueue, const void * const pvItemToQueue, TickType_t xTicksToWait, const BaseType_t xCopyPosition );
|
||||
BaseType_t MPU_xQueueReceive( QueueHandle_t xQueue, void * const pvBuffer, TickType_t xTicksToWait );
|
||||
BaseType_t MPU_xQueuePeek( QueueHandle_t xQueue, void * const pvBuffer, TickType_t xTicksToWait );
|
||||
BaseType_t MPU_xQueueSemaphoreTake( QueueHandle_t xQueue, TickType_t xTicksToWait );
|
||||
UBaseType_t MPU_uxQueueMessagesWaiting( const QueueHandle_t xQueue );
|
||||
UBaseType_t MPU_uxQueueSpacesAvailable( const QueueHandle_t xQueue );
|
||||
void MPU_vQueueDelete( QueueHandle_t xQueue );
|
||||
QueueHandle_t MPU_xQueueCreateMutex( const uint8_t ucQueueType );
|
||||
QueueHandle_t MPU_xQueueCreateMutexStatic( const uint8_t ucQueueType, StaticQueue_t *pxStaticQueue );
|
||||
QueueHandle_t MPU_xQueueCreateCountingSemaphore( const UBaseType_t uxMaxCount, const UBaseType_t uxInitialCount );
|
||||
QueueHandle_t MPU_xQueueCreateCountingSemaphoreStatic( const UBaseType_t uxMaxCount, const UBaseType_t uxInitialCount, StaticQueue_t *pxStaticQueue );
|
||||
void* MPU_xQueueGetMutexHolder( QueueHandle_t xSemaphore );
|
||||
BaseType_t MPU_xQueueTakeMutexRecursive( QueueHandle_t xMutex, TickType_t xTicksToWait );
|
||||
BaseType_t MPU_xQueueGiveMutexRecursive( QueueHandle_t pxMutex );
|
||||
void MPU_vQueueAddToRegistry( QueueHandle_t xQueue, const char *pcName );
|
||||
void MPU_vQueueUnregisterQueue( QueueHandle_t xQueue );
|
||||
const char * MPU_pcQueueGetName( QueueHandle_t xQueue );
|
||||
QueueHandle_t MPU_xQueueGenericCreate( const UBaseType_t uxQueueLength, const UBaseType_t uxItemSize, const uint8_t ucQueueType );
|
||||
QueueHandle_t MPU_xQueueGenericCreateStatic( const UBaseType_t uxQueueLength, const UBaseType_t uxItemSize, uint8_t *pucQueueStorage, StaticQueue_t *pxStaticQueue, const uint8_t ucQueueType );
|
||||
QueueSetHandle_t MPU_xQueueCreateSet( const UBaseType_t uxEventQueueLength );
|
||||
BaseType_t MPU_xQueueAddToSet( QueueSetMemberHandle_t xQueueOrSemaphore, QueueSetHandle_t xQueueSet );
|
||||
BaseType_t MPU_xQueueRemoveFromSet( QueueSetMemberHandle_t xQueueOrSemaphore, QueueSetHandle_t xQueueSet );
|
||||
QueueSetMemberHandle_t MPU_xQueueSelectFromSet( QueueSetHandle_t xQueueSet, const TickType_t xTicksToWait );
|
||||
BaseType_t MPU_xQueueGenericReset( QueueHandle_t xQueue, BaseType_t xNewQueue );
|
||||
void MPU_vQueueSetQueueNumber( QueueHandle_t xQueue, UBaseType_t uxQueueNumber );
|
||||
UBaseType_t MPU_uxQueueGetQueueNumber( QueueHandle_t xQueue );
|
||||
uint8_t MPU_ucQueueGetQueueType( QueueHandle_t xQueue );
|
||||
|
||||
/* MPU versions of timers.h API functions. */
|
||||
TimerHandle_t MPU_xTimerCreate( const char * const pcTimerName, const TickType_t xTimerPeriodInTicks, const UBaseType_t uxAutoReload, void * const pvTimerID, TimerCallbackFunction_t pxCallbackFunction );
|
||||
TimerHandle_t MPU_xTimerCreateStatic( const char * const pcTimerName, const TickType_t xTimerPeriodInTicks, const UBaseType_t uxAutoReload, void * const pvTimerID, TimerCallbackFunction_t pxCallbackFunction, StaticTimer_t *pxTimerBuffer );
|
||||
void * MPU_pvTimerGetTimerID( const TimerHandle_t xTimer );
|
||||
void MPU_vTimerSetTimerID( TimerHandle_t xTimer, void *pvNewID );
|
||||
BaseType_t MPU_xTimerIsTimerActive( TimerHandle_t xTimer );
|
||||
TaskHandle_t MPU_xTimerGetTimerDaemonTaskHandle( void );
|
||||
BaseType_t MPU_xTimerPendFunctionCall( PendedFunction_t xFunctionToPend, void *pvParameter1, uint32_t ulParameter2, TickType_t xTicksToWait );
|
||||
const char * MPU_pcTimerGetName( TimerHandle_t xTimer );
|
||||
TickType_t MPU_xTimerGetPeriod( TimerHandle_t xTimer );
|
||||
TickType_t MPU_xTimerGetExpiryTime( TimerHandle_t xTimer );
|
||||
BaseType_t MPU_xTimerCreateTimerTask( void );
|
||||
BaseType_t MPU_xTimerGenericCommand( TimerHandle_t xTimer, const BaseType_t xCommandID, const TickType_t xOptionalValue, BaseType_t * const pxHigherPriorityTaskWoken, const TickType_t xTicksToWait );
|
||||
|
||||
/* MPU versions of event_group.h API functions. */
|
||||
EventGroupHandle_t MPU_xEventGroupCreate( void );
|
||||
EventGroupHandle_t MPU_xEventGroupCreateStatic( StaticEventGroup_t *pxEventGroupBuffer );
|
||||
EventBits_t MPU_xEventGroupWaitBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToWaitFor, const BaseType_t xClearOnExit, const BaseType_t xWaitForAllBits, TickType_t xTicksToWait );
|
||||
EventBits_t MPU_xEventGroupClearBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToClear );
|
||||
EventBits_t MPU_xEventGroupSetBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet );
|
||||
EventBits_t MPU_xEventGroupSync( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet, const EventBits_t uxBitsToWaitFor, TickType_t xTicksToWait );
|
||||
void MPU_vEventGroupDelete( EventGroupHandle_t xEventGroup );
|
||||
UBaseType_t MPU_uxEventGroupGetNumber( void* xEventGroup );
|
||||
|
||||
/* MPU versions of message/stream_buffer.h API functions. */
|
||||
size_t MPU_xStreamBufferSend( StreamBufferHandle_t xStreamBuffer, const void *pvTxData, size_t xDataLengthBytes, TickType_t xTicksToWait );
|
||||
size_t MPU_xStreamBufferSendFromISR( StreamBufferHandle_t xStreamBuffer, const void *pvTxData, size_t xDataLengthBytes, BaseType_t * const pxHigherPriorityTaskWoken );
|
||||
size_t MPU_xStreamBufferReceive( StreamBufferHandle_t xStreamBuffer, void *pvRxData, size_t xBufferLengthBytes, TickType_t xTicksToWait );
|
||||
size_t MPU_xStreamBufferReceiveFromISR( StreamBufferHandle_t xStreamBuffer, void *pvRxData, size_t xBufferLengthBytes, BaseType_t * const pxHigherPriorityTaskWoken );
|
||||
void MPU_vStreamBufferDelete( StreamBufferHandle_t xStreamBuffer );
|
||||
BaseType_t MPU_xStreamBufferIsFull( StreamBufferHandle_t xStreamBuffer );
|
||||
BaseType_t MPU_xStreamBufferIsEmpty( StreamBufferHandle_t xStreamBuffer );
|
||||
BaseType_t MPU_xStreamBufferReset( StreamBufferHandle_t xStreamBuffer );
|
||||
size_t MPU_xStreamBufferSpacesAvailable( StreamBufferHandle_t xStreamBuffer );
|
||||
size_t MPU_xStreamBufferBytesAvailable( StreamBufferHandle_t xStreamBuffer );
|
||||
BaseType_t MPU_xStreamBufferSetTriggerLevel( StreamBufferHandle_t xStreamBuffer, size_t xTriggerLevel );
|
||||
StreamBufferHandle_t MPU_xStreamBufferGenericCreate( size_t xBufferSizeBytes, size_t xTriggerLevelBytes, BaseType_t xIsMessageBuffer );
|
||||
StreamBufferHandle_t MPU_xStreamBufferGenericCreateStatic( size_t xBufferSizeBytes, size_t xTriggerLevelBytes, BaseType_t xIsMessageBuffer, uint8_t * const pucStreamBufferStorageArea, StaticStreamBuffer_t * const pxStaticStreamBuffer );
|
||||
|
||||
|
||||
|
||||
#endif /* MPU_PROTOTYPES_H */
|
||||
|
||||
@@ -1,195 +0,0 @@
|
||||
/* Copyright 2018 Canaan Inc.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* http://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.
|
||||
*/
|
||||
/*
|
||||
* FreeRTOS Kernel V10.0.1
|
||||
* Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* http://www.FreeRTOS.org
|
||||
* http://aws.amazon.com/freertos
|
||||
*
|
||||
* 1 tab == 4 spaces!
|
||||
*/
|
||||
|
||||
#ifndef MPU_WRAPPERS_H
|
||||
#define MPU_WRAPPERS_H
|
||||
|
||||
/* This file redefines API functions to be called through a wrapper macro, but
|
||||
only for ports that are using the MPU. */
|
||||
#ifdef portUSING_MPU_WRAPPERS
|
||||
|
||||
/* MPU_WRAPPERS_INCLUDED_FROM_API_FILE will be defined when this file is
|
||||
included from queue.c or task.c to prevent it from having an effect within
|
||||
those files. */
|
||||
#ifndef MPU_WRAPPERS_INCLUDED_FROM_API_FILE
|
||||
|
||||
/*
|
||||
* Map standard (non MPU) API functions to equivalents that start
|
||||
* "MPU_". This will cause the application code to call the MPU_
|
||||
* version, which wraps the non-MPU version with privilege promoting
|
||||
* then demoting code, so the kernel code always runs will full
|
||||
* privileges.
|
||||
*/
|
||||
|
||||
/* Map standard tasks.h API functions to the MPU equivalents. */
|
||||
#define xTaskCreate MPU_xTaskCreate
|
||||
#define xTaskCreateStatic MPU_xTaskCreateStatic
|
||||
#define xTaskCreateRestricted MPU_xTaskCreateRestricted
|
||||
#define vTaskAllocateMPURegions MPU_vTaskAllocateMPURegions
|
||||
#define vTaskDelete MPU_vTaskDelete
|
||||
#define vTaskDelay MPU_vTaskDelay
|
||||
#define vTaskDelayUntil MPU_vTaskDelayUntil
|
||||
#define xTaskAbortDelay MPU_xTaskAbortDelay
|
||||
#define uxTaskPriorityGet MPU_uxTaskPriorityGet
|
||||
#define eTaskGetState MPU_eTaskGetState
|
||||
#define vTaskGetInfo MPU_vTaskGetInfo
|
||||
#define vTaskPrioritySet MPU_vTaskPrioritySet
|
||||
#define vTaskSuspend MPU_vTaskSuspend
|
||||
#define vTaskResume MPU_vTaskResume
|
||||
#define vTaskSuspendAll MPU_vTaskSuspendAll
|
||||
#define xTaskResumeAll MPU_xTaskResumeAll
|
||||
#define xTaskGetTickCount MPU_xTaskGetTickCount
|
||||
#define uxTaskGetNumberOfTasks MPU_uxTaskGetNumberOfTasks
|
||||
#define pcTaskGetName MPU_pcTaskGetName
|
||||
#define xTaskGetHandle MPU_xTaskGetHandle
|
||||
#define uxTaskGetStackHighWaterMark MPU_uxTaskGetStackHighWaterMark
|
||||
#define vTaskSetApplicationTaskTag MPU_vTaskSetApplicationTaskTag
|
||||
#define xTaskGetApplicationTaskTag MPU_xTaskGetApplicationTaskTag
|
||||
#define vTaskSetThreadLocalStoragePointer MPU_vTaskSetThreadLocalStoragePointer
|
||||
#define pvTaskGetThreadLocalStoragePointer MPU_pvTaskGetThreadLocalStoragePointer
|
||||
#define xTaskCallApplicationTaskHook MPU_xTaskCallApplicationTaskHook
|
||||
#define xTaskGetIdleTaskHandle MPU_xTaskGetIdleTaskHandle
|
||||
#define uxTaskGetSystemState MPU_uxTaskGetSystemState
|
||||
#define vTaskList MPU_vTaskList
|
||||
#define vTaskGetRunTimeStats MPU_vTaskGetRunTimeStats
|
||||
#define xTaskGenericNotify MPU_xTaskGenericNotify
|
||||
#define xTaskNotifyWait MPU_xTaskNotifyWait
|
||||
#define ulTaskNotifyTake MPU_ulTaskNotifyTake
|
||||
#define xTaskNotifyStateClear MPU_xTaskNotifyStateClear
|
||||
|
||||
#define xTaskGetCurrentTaskHandle MPU_xTaskGetCurrentTaskHandle
|
||||
#define vTaskSetTimeOutState MPU_vTaskSetTimeOutState
|
||||
#define xTaskCheckForTimeOut MPU_xTaskCheckForTimeOut
|
||||
#define xTaskGetSchedulerState MPU_xTaskGetSchedulerState
|
||||
|
||||
/* Map standard queue.h API functions to the MPU equivalents. */
|
||||
#define xQueueGenericSend MPU_xQueueGenericSend
|
||||
#define xQueueReceive MPU_xQueueReceive
|
||||
#define xQueuePeek MPU_xQueuePeek
|
||||
#define xQueueSemaphoreTake MPU_xQueueSemaphoreTake
|
||||
#define uxQueueMessagesWaiting MPU_uxQueueMessagesWaiting
|
||||
#define uxQueueSpacesAvailable MPU_uxQueueSpacesAvailable
|
||||
#define vQueueDelete MPU_vQueueDelete
|
||||
#define xQueueCreateMutex MPU_xQueueCreateMutex
|
||||
#define xQueueCreateMutexStatic MPU_xQueueCreateMutexStatic
|
||||
#define xQueueCreateCountingSemaphore MPU_xQueueCreateCountingSemaphore
|
||||
#define xQueueCreateCountingSemaphoreStatic MPU_xQueueCreateCountingSemaphoreStatic
|
||||
#define xQueueGetMutexHolder MPU_xQueueGetMutexHolder
|
||||
#define xQueueTakeMutexRecursive MPU_xQueueTakeMutexRecursive
|
||||
#define xQueueGiveMutexRecursive MPU_xQueueGiveMutexRecursive
|
||||
#define xQueueGenericCreate MPU_xQueueGenericCreate
|
||||
#define xQueueGenericCreateStatic MPU_xQueueGenericCreateStatic
|
||||
#define xQueueCreateSet MPU_xQueueCreateSet
|
||||
#define xQueueAddToSet MPU_xQueueAddToSet
|
||||
#define xQueueRemoveFromSet MPU_xQueueRemoveFromSet
|
||||
#define xQueueSelectFromSet MPU_xQueueSelectFromSet
|
||||
#define xQueueGenericReset MPU_xQueueGenericReset
|
||||
|
||||
#if( configQUEUE_REGISTRY_SIZE > 0 )
|
||||
#define vQueueAddToRegistry MPU_vQueueAddToRegistry
|
||||
#define vQueueUnregisterQueue MPU_vQueueUnregisterQueue
|
||||
#define pcQueueGetName MPU_pcQueueGetName
|
||||
#endif
|
||||
|
||||
/* Map standard timer.h API functions to the MPU equivalents. */
|
||||
#define xTimerCreate MPU_xTimerCreate
|
||||
#define xTimerCreateStatic MPU_xTimerCreateStatic
|
||||
#define pvTimerGetTimerID MPU_pvTimerGetTimerID
|
||||
#define vTimerSetTimerID MPU_vTimerSetTimerID
|
||||
#define xTimerIsTimerActive MPU_xTimerIsTimerActive
|
||||
#define xTimerGetTimerDaemonTaskHandle MPU_xTimerGetTimerDaemonTaskHandle
|
||||
#define xTimerPendFunctionCall MPU_xTimerPendFunctionCall
|
||||
#define pcTimerGetName MPU_pcTimerGetName
|
||||
#define xTimerGetPeriod MPU_xTimerGetPeriod
|
||||
#define xTimerGetExpiryTime MPU_xTimerGetExpiryTime
|
||||
#define xTimerGenericCommand MPU_xTimerGenericCommand
|
||||
|
||||
/* Map standard event_group.h API functions to the MPU equivalents. */
|
||||
#define xEventGroupCreate MPU_xEventGroupCreate
|
||||
#define xEventGroupCreateStatic MPU_xEventGroupCreateStatic
|
||||
#define xEventGroupWaitBits MPU_xEventGroupWaitBits
|
||||
#define xEventGroupClearBits MPU_xEventGroupClearBits
|
||||
#define xEventGroupSetBits MPU_xEventGroupSetBits
|
||||
#define xEventGroupSync MPU_xEventGroupSync
|
||||
#define vEventGroupDelete MPU_vEventGroupDelete
|
||||
|
||||
/* Map standard message/stream_buffer.h API functions to the MPU
|
||||
equivalents. */
|
||||
#define xStreamBufferSend MPU_xStreamBufferSend
|
||||
#define xStreamBufferSendFromISR MPU_xStreamBufferSendFromISR
|
||||
#define xStreamBufferReceive MPU_xStreamBufferReceive
|
||||
#define xStreamBufferReceiveFromISR MPU_xStreamBufferReceiveFromISR
|
||||
#define vStreamBufferDelete MPU_vStreamBufferDelete
|
||||
#define xStreamBufferIsFull MPU_xStreamBufferIsFull
|
||||
#define xStreamBufferIsEmpty MPU_xStreamBufferIsEmpty
|
||||
#define xStreamBufferReset MPU_xStreamBufferReset
|
||||
#define xStreamBufferSpacesAvailable MPU_xStreamBufferSpacesAvailable
|
||||
#define xStreamBufferBytesAvailable MPU_xStreamBufferBytesAvailable
|
||||
#define xStreamBufferSetTriggerLevel MPU_xStreamBufferSetTriggerLevel
|
||||
#define xStreamBufferGenericCreate MPU_xStreamBufferGenericCreate
|
||||
#define xStreamBufferGenericCreateStatic MPU_xStreamBufferGenericCreateStatic
|
||||
|
||||
|
||||
/* Remove the privileged function macro, but keep the PRIVILEGED_DATA
|
||||
macro so applications can place data in privileged access sections
|
||||
(useful when using statically allocated objects). */
|
||||
#define PRIVILEGED_FUNCTION
|
||||
#define PRIVILEGED_DATA __attribute__((section("privileged_data")))
|
||||
|
||||
#else /* MPU_WRAPPERS_INCLUDED_FROM_API_FILE */
|
||||
|
||||
/* Ensure API functions go in the privileged execution section. */
|
||||
#define PRIVILEGED_FUNCTION __attribute__((section("privileged_functions")))
|
||||
#define PRIVILEGED_DATA __attribute__((section("privileged_data")))
|
||||
|
||||
#endif /* MPU_WRAPPERS_INCLUDED_FROM_API_FILE */
|
||||
|
||||
#else /* portUSING_MPU_WRAPPERS */
|
||||
|
||||
#define PRIVILEGED_FUNCTION
|
||||
#define PRIVILEGED_DATA
|
||||
#define portUSING_MPU_WRAPPERS 0
|
||||
|
||||
#endif /* portUSING_MPU_WRAPPERS */
|
||||
|
||||
|
||||
#endif /* MPU_WRAPPERS_H */
|
||||
|
||||
@@ -1,178 +0,0 @@
|
||||
/* Copyright 2018 Canaan Inc.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* http://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.
|
||||
*/
|
||||
/*
|
||||
* FreeRTOS Kernel V10.0.1
|
||||
* Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* http://www.FreeRTOS.org
|
||||
* http://aws.amazon.com/freertos
|
||||
*
|
||||
* 1 tab == 4 spaces!
|
||||
*/
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* Portable layer API. Each function must be defined for each port.
|
||||
*----------------------------------------------------------*/
|
||||
|
||||
#ifndef PORTABLE_H
|
||||
#define PORTABLE_H
|
||||
|
||||
/* Each FreeRTOS port has a unique portmacro.h header file. Originally a
|
||||
pre-processor definition was used to ensure the pre-processor found the correct
|
||||
portmacro.h file for the port being used. That scheme was deprecated in favour
|
||||
of setting the compiler's include path such that it found the correct
|
||||
portmacro.h file - removing the need for the constant and allowing the
|
||||
portmacro.h file to be located anywhere in relation to the port being used.
|
||||
Purely for reasons of backward compatibility the old method is still valid, but
|
||||
to make it clear that new projects should not use it, support for the port
|
||||
specific constants has been moved into the deprecated_definitions.h header
|
||||
file. */
|
||||
|
||||
/* If portENTER_CRITICAL is not defined then including deprecated_definitions.h
|
||||
did not result in a portmacro.h header file being included - and it should be
|
||||
included here. In this case the path to the correct portmacro.h header file
|
||||
must be set in the compiler's include path. */
|
||||
#ifndef portENTER_CRITICAL
|
||||
#include "portmacro.h"
|
||||
#endif
|
||||
|
||||
#if portBYTE_ALIGNMENT == 32
|
||||
#define portBYTE_ALIGNMENT_MASK ( 0x001f )
|
||||
#endif
|
||||
|
||||
#if portBYTE_ALIGNMENT == 16
|
||||
#define portBYTE_ALIGNMENT_MASK ( 0x000f )
|
||||
#endif
|
||||
|
||||
#if portBYTE_ALIGNMENT == 8
|
||||
#define portBYTE_ALIGNMENT_MASK ( 0x0007 )
|
||||
#endif
|
||||
|
||||
#if portBYTE_ALIGNMENT == 4
|
||||
#define portBYTE_ALIGNMENT_MASK ( 0x0003 )
|
||||
#endif
|
||||
|
||||
#if portBYTE_ALIGNMENT == 2
|
||||
#define portBYTE_ALIGNMENT_MASK ( 0x0001 )
|
||||
#endif
|
||||
|
||||
#if portBYTE_ALIGNMENT == 1
|
||||
#define portBYTE_ALIGNMENT_MASK ( 0x0000 )
|
||||
#endif
|
||||
|
||||
#ifndef portBYTE_ALIGNMENT_MASK
|
||||
#error "Invalid portBYTE_ALIGNMENT definition"
|
||||
#endif
|
||||
|
||||
#ifndef portNUM_CONFIGURABLE_REGIONS
|
||||
#define portNUM_CONFIGURABLE_REGIONS 1
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "mpu_wrappers.h"
|
||||
|
||||
/*
|
||||
* Setup the stack of a new task so it is ready to be placed under the
|
||||
* scheduler control. The registers have to be placed on the stack in
|
||||
* the order that the port expects to find them.
|
||||
*
|
||||
*/
|
||||
#if( portUSING_MPU_WRAPPERS == 1 )
|
||||
StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters, BaseType_t xRunPrivileged ) PRIVILEGED_FUNCTION;
|
||||
#else
|
||||
StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters ) PRIVILEGED_FUNCTION;
|
||||
#endif
|
||||
|
||||
/* Used by heap_5.c. */
|
||||
typedef struct HeapRegion
|
||||
{
|
||||
uint8_t *pucStartAddress;
|
||||
size_t xSizeInBytes;
|
||||
} HeapRegion_t;
|
||||
|
||||
/*
|
||||
* Used to define multiple heap regions for use by heap_5.c. This function
|
||||
* must be called before any calls to pvPortMalloc() - not creating a task,
|
||||
* queue, semaphore, mutex, software timer, event group, etc. will result in
|
||||
* pvPortMalloc being called.
|
||||
*
|
||||
* pxHeapRegions passes in an array of HeapRegion_t structures - each of which
|
||||
* defines a region of memory that can be used as the heap. The array is
|
||||
* terminated by a HeapRegions_t structure that has a size of 0. The region
|
||||
* with the lowest start address must appear first in the array.
|
||||
*/
|
||||
void vPortDefineHeapRegions( const HeapRegion_t * const pxHeapRegions ) PRIVILEGED_FUNCTION;
|
||||
|
||||
|
||||
/*
|
||||
* Map to the memory management routines required for the port.
|
||||
*/
|
||||
void *pvPortMalloc( size_t xSize ) PRIVILEGED_FUNCTION;
|
||||
void vPortFree( void *pv ) PRIVILEGED_FUNCTION;
|
||||
void vPortInitialiseBlocks( void ) PRIVILEGED_FUNCTION;
|
||||
size_t xPortGetFreeHeapSize( void ) PRIVILEGED_FUNCTION;
|
||||
size_t xPortGetMinimumEverFreeHeapSize( void ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/*
|
||||
* Setup the hardware ready for the scheduler to take control. This generally
|
||||
* sets up a tick interrupt and sets timers for the correct tick frequency.
|
||||
*/
|
||||
BaseType_t xPortStartScheduler( void ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/*
|
||||
* Undo any hardware/ISR setup that was performed by xPortStartScheduler() so
|
||||
* the hardware is left in its original condition after the scheduler stops
|
||||
* executing.
|
||||
*/
|
||||
void vPortEndScheduler( void ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/*
|
||||
* The structures and methods of manipulating the MPU are contained within the
|
||||
* port layer.
|
||||
*
|
||||
* Fills the xMPUSettings structure with the memory region information
|
||||
* contained in xRegions.
|
||||
*/
|
||||
#if( portUSING_MPU_WRAPPERS == 1 )
|
||||
struct xMEMORY_REGION;
|
||||
void vPortStoreTaskMPUSettings( xMPU_SETTINGS *xMPUSettings, const struct xMEMORY_REGION * const xRegions, StackType_t *pxBottomOfStack, uint32_t ulStackDepth ) PRIVILEGED_FUNCTION;
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* PORTABLE_H */
|
||||
|
||||
@@ -1,138 +0,0 @@
|
||||
/* Copyright 2018 Canaan Inc.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* http://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.
|
||||
*/
|
||||
/*
|
||||
* FreeRTOS Kernel V10.0.1
|
||||
* Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* http://www.FreeRTOS.org
|
||||
* http://aws.amazon.com/freertos
|
||||
*
|
||||
* 1 tab == 4 spaces!
|
||||
*/
|
||||
|
||||
#ifndef PROJDEFS_H
|
||||
#define PROJDEFS_H
|
||||
|
||||
/*
|
||||
* Defines the prototype to which task functions must conform. Defined in this
|
||||
* file to ensure the type is known before portable.h is included.
|
||||
*/
|
||||
typedef void (*TaskFunction_t)( void * );
|
||||
|
||||
/* Converts a time in milliseconds to a time in ticks. This macro can be
|
||||
overridden by a macro of the same name defined in FreeRTOSConfig.h in case the
|
||||
definition here is not suitable for your application. */
|
||||
#ifndef pdMS_TO_TICKS
|
||||
#define pdMS_TO_TICKS( xTimeInMs ) ( ( TickType_t ) ( ( ( TickType_t ) ( xTimeInMs ) * ( TickType_t ) configTICK_RATE_HZ ) / ( TickType_t ) 1000 ) )
|
||||
#endif
|
||||
|
||||
#define pdFALSE ( ( BaseType_t ) 0 )
|
||||
#define pdTRUE ( ( BaseType_t ) 1 )
|
||||
|
||||
#define pdPASS ( pdTRUE )
|
||||
#define pdFAIL ( pdFALSE )
|
||||
#define errQUEUE_EMPTY ( ( BaseType_t ) 0 )
|
||||
#define errQUEUE_FULL ( ( BaseType_t ) 0 )
|
||||
|
||||
/* FreeRTOS error definitions. */
|
||||
#define errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY ( -1 )
|
||||
#define errQUEUE_BLOCKED ( -4 )
|
||||
#define errQUEUE_YIELD ( -5 )
|
||||
|
||||
/* Macros used for basic data corruption checks. */
|
||||
#ifndef configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES
|
||||
#define configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES 0
|
||||
#endif
|
||||
|
||||
#if( configUSE_16_BIT_TICKS == 1 )
|
||||
#define pdINTEGRITY_CHECK_VALUE 0x5a5a
|
||||
#else
|
||||
#define pdINTEGRITY_CHECK_VALUE 0x5a5a5a5aUL
|
||||
#endif
|
||||
|
||||
/* The following errno values are used by FreeRTOS+ components, not FreeRTOS
|
||||
itself. */
|
||||
#define pdFREERTOS_ERRNO_NONE 0 /* No errors */
|
||||
#define pdFREERTOS_ERRNO_ENOENT 2 /* No such file or directory */
|
||||
#define pdFREERTOS_ERRNO_EINTR 4 /* Interrupted system call */
|
||||
#define pdFREERTOS_ERRNO_EIO 5 /* I/O error */
|
||||
#define pdFREERTOS_ERRNO_ENXIO 6 /* No such device or address */
|
||||
#define pdFREERTOS_ERRNO_EBADF 9 /* Bad file number */
|
||||
#define pdFREERTOS_ERRNO_EAGAIN 11 /* No more processes */
|
||||
#define pdFREERTOS_ERRNO_EWOULDBLOCK 11 /* Operation would block */
|
||||
#define pdFREERTOS_ERRNO_ENOMEM 12 /* Not enough memory */
|
||||
#define pdFREERTOS_ERRNO_EACCES 13 /* Permission denied */
|
||||
#define pdFREERTOS_ERRNO_EFAULT 14 /* Bad address */
|
||||
#define pdFREERTOS_ERRNO_EBUSY 16 /* Mount device busy */
|
||||
#define pdFREERTOS_ERRNO_EEXIST 17 /* File exists */
|
||||
#define pdFREERTOS_ERRNO_EXDEV 18 /* Cross-device link */
|
||||
#define pdFREERTOS_ERRNO_ENODEV 19 /* No such device */
|
||||
#define pdFREERTOS_ERRNO_ENOTDIR 20 /* Not a directory */
|
||||
#define pdFREERTOS_ERRNO_EISDIR 21 /* Is a directory */
|
||||
#define pdFREERTOS_ERRNO_EINVAL 22 /* Invalid argument */
|
||||
#define pdFREERTOS_ERRNO_ENOSPC 28 /* No space left on device */
|
||||
#define pdFREERTOS_ERRNO_ESPIPE 29 /* Illegal seek */
|
||||
#define pdFREERTOS_ERRNO_EROFS 30 /* Read only file system */
|
||||
#define pdFREERTOS_ERRNO_EUNATCH 42 /* Protocol driver not attached */
|
||||
#define pdFREERTOS_ERRNO_EBADE 50 /* Invalid exchange */
|
||||
#define pdFREERTOS_ERRNO_EFTYPE 79 /* Inappropriate file type or format */
|
||||
#define pdFREERTOS_ERRNO_ENMFILE 89 /* No more files */
|
||||
#define pdFREERTOS_ERRNO_ENOTEMPTY 90 /* Directory not empty */
|
||||
#define pdFREERTOS_ERRNO_ENAMETOOLONG 91 /* File or path name too long */
|
||||
#define pdFREERTOS_ERRNO_EOPNOTSUPP 95 /* Operation not supported on transport endpoint */
|
||||
#define pdFREERTOS_ERRNO_ENOBUFS 105 /* No buffer space available */
|
||||
#define pdFREERTOS_ERRNO_ENOPROTOOPT 109 /* Protocol not available */
|
||||
#define pdFREERTOS_ERRNO_EADDRINUSE 112 /* Address already in use */
|
||||
#define pdFREERTOS_ERRNO_ETIMEDOUT 116 /* Connection timed out */
|
||||
#define pdFREERTOS_ERRNO_EINPROGRESS 119 /* Connection already in progress */
|
||||
#define pdFREERTOS_ERRNO_EALREADY 120 /* Socket already connected */
|
||||
#define pdFREERTOS_ERRNO_EADDRNOTAVAIL 125 /* Address not available */
|
||||
#define pdFREERTOS_ERRNO_EISCONN 127 /* Socket is already connected */
|
||||
#define pdFREERTOS_ERRNO_ENOTCONN 128 /* Socket is not connected */
|
||||
#define pdFREERTOS_ERRNO_ENOMEDIUM 135 /* No medium inserted */
|
||||
#define pdFREERTOS_ERRNO_EILSEQ 138 /* An invalid UTF-16 sequence was encountered. */
|
||||
#define pdFREERTOS_ERRNO_ECANCELED 140 /* Operation canceled. */
|
||||
|
||||
/* The following endian values are used by FreeRTOS+ components, not FreeRTOS
|
||||
itself. */
|
||||
#define pdFREERTOS_LITTLE_ENDIAN 0
|
||||
#define pdFREERTOS_BIG_ENDIAN 1
|
||||
|
||||
/* Re-defining endian values for generic naming. */
|
||||
#define pdLITTLE_ENDIAN pdFREERTOS_LITTLE_ENDIAN
|
||||
#define pdBIG_ENDIAN pdFREERTOS_BIG_ENDIAN
|
||||
|
||||
|
||||
#endif /* PROJDEFS_H */
|
||||
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,143 +0,0 @@
|
||||
/* Copyright 2018 Canaan Inc.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* http://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.
|
||||
*/
|
||||
/*
|
||||
* FreeRTOS Kernel V10.0.1
|
||||
* Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* http://www.FreeRTOS.org
|
||||
* http://aws.amazon.com/freertos
|
||||
*
|
||||
* 1 tab == 4 spaces!
|
||||
*/
|
||||
|
||||
#ifndef STACK_MACROS_H
|
||||
#define STACK_MACROS_H
|
||||
|
||||
/*
|
||||
* Call the stack overflow hook function if the stack of the task being swapped
|
||||
* out is currently overflowed, or looks like it might have overflowed in the
|
||||
* past.
|
||||
*
|
||||
* Setting configCHECK_FOR_STACK_OVERFLOW to 1 will cause the macro to check
|
||||
* the current stack state only - comparing the current top of stack value to
|
||||
* the stack limit. Setting configCHECK_FOR_STACK_OVERFLOW to greater than 1
|
||||
* will also cause the last few stack bytes to be checked to ensure the value
|
||||
* to which the bytes were set when the task was created have not been
|
||||
* overwritten. Note this second test does not guarantee that an overflowed
|
||||
* stack will always be recognised.
|
||||
*/
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if( ( configCHECK_FOR_STACK_OVERFLOW == 1 ) && ( portSTACK_GROWTH < 0 ) )
|
||||
|
||||
/* Only the current stack state is to be checked. */
|
||||
#define taskCHECK_FOR_STACK_OVERFLOW() \
|
||||
{ \
|
||||
/* Is the currently saved stack pointer within the stack limit? */ \
|
||||
if( pxCurrentTCB[uxPsrId]->pxTopOfStack <= pxCurrentTCB[uxPsrId]->pxStack ) \
|
||||
{ \
|
||||
vApplicationStackOverflowHook( ( TaskHandle_t ) pxCurrentTCB[uxPsrId], pxCurrentTCB[uxPsrId]->pcTaskName ); \
|
||||
} \
|
||||
}
|
||||
|
||||
#endif /* configCHECK_FOR_STACK_OVERFLOW == 1 */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if( ( configCHECK_FOR_STACK_OVERFLOW == 1 ) && ( portSTACK_GROWTH > 0 ) )
|
||||
|
||||
/* Only the current stack state is to be checked. */
|
||||
#define taskCHECK_FOR_STACK_OVERFLOW() \
|
||||
{ \
|
||||
\
|
||||
/* Is the currently saved stack pointer within the stack limit? */ \
|
||||
if( pxCurrentTCB->pxTopOfStack >= pxCurrentTCB->pxEndOfStack ) \
|
||||
{ \
|
||||
vApplicationStackOverflowHook( ( TaskHandle_t ) pxCurrentTCB, pxCurrentTCB->pcTaskName ); \
|
||||
} \
|
||||
}
|
||||
|
||||
#endif /* configCHECK_FOR_STACK_OVERFLOW == 1 */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if( ( configCHECK_FOR_STACK_OVERFLOW > 1 ) && ( portSTACK_GROWTH < 0 ) )
|
||||
|
||||
#define taskCHECK_FOR_STACK_OVERFLOW() \
|
||||
{ \
|
||||
const uint32_t * const pulStack = ( uint32_t * ) pxCurrentTCB->pxStack; \
|
||||
const uint32_t ulCheckValue = ( uint32_t ) 0xa5a5a5a5; \
|
||||
\
|
||||
if( ( pulStack[ 0 ] != ulCheckValue ) || \
|
||||
( pulStack[ 1 ] != ulCheckValue ) || \
|
||||
( pulStack[ 2 ] != ulCheckValue ) || \
|
||||
( pulStack[ 3 ] != ulCheckValue ) ) \
|
||||
{ \
|
||||
vApplicationStackOverflowHook( ( TaskHandle_t ) pxCurrentTCB, pxCurrentTCB->pcTaskName ); \
|
||||
} \
|
||||
}
|
||||
|
||||
#endif /* #if( configCHECK_FOR_STACK_OVERFLOW > 1 ) */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if( ( configCHECK_FOR_STACK_OVERFLOW > 1 ) && ( portSTACK_GROWTH > 0 ) )
|
||||
|
||||
#define taskCHECK_FOR_STACK_OVERFLOW() \
|
||||
{ \
|
||||
int8_t *pcEndOfStack = ( int8_t * ) pxCurrentTCB->pxEndOfStack; \
|
||||
static const uint8_t ucExpectedStackBytes[] = { tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \
|
||||
tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \
|
||||
tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \
|
||||
tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \
|
||||
tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE }; \
|
||||
\
|
||||
\
|
||||
pcEndOfStack -= sizeof( ucExpectedStackBytes ); \
|
||||
\
|
||||
/* Has the extremity of the task stack ever been written over? */ \
|
||||
if( memcmp( ( void * ) pcEndOfStack, ( void * ) ucExpectedStackBytes, sizeof( ucExpectedStackBytes ) ) != 0 ) \
|
||||
{ \
|
||||
vApplicationStackOverflowHook( ( TaskHandle_t ) pxCurrentTCB, pxCurrentTCB->pcTaskName ); \
|
||||
} \
|
||||
}
|
||||
|
||||
#endif /* #if( configCHECK_FOR_STACK_OVERFLOW > 1 ) */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Remove stack overflow macro if not being used. */
|
||||
#ifndef taskCHECK_FOR_STACK_OVERFLOW
|
||||
#define taskCHECK_FOR_STACK_OVERFLOW()
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#endif /* STACK_MACROS_H */
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
|
||||
#ifndef FREERTOS_STDINT
|
||||
#define FREERTOS_STDINT
|
||||
|
||||
/*******************************************************************************
|
||||
* THIS IS NOT A FULL stdint.h IMPLEMENTATION - It only contains the definitions
|
||||
* necessary to build the FreeRTOS code. It is provided to allow FreeRTOS to be
|
||||
* built using compilers that do not provide their own stdint.h definition.
|
||||
*
|
||||
* To use this file:
|
||||
*
|
||||
* 1) Copy this file into the directory that contains your FreeRTOSConfig.h
|
||||
* header file, as that directory will already be in the compilers include
|
||||
* path.
|
||||
*
|
||||
* 2) Rename the copied file stdint.h.
|
||||
*
|
||||
*/
|
||||
|
||||
typedef signed char int8_t;
|
||||
typedef unsigned char uint8_t;
|
||||
typedef short int16_t;
|
||||
typedef unsigned short uint16_t;
|
||||
typedef long int32_t;
|
||||
typedef unsigned long uint32_t;
|
||||
|
||||
#endif /* FREERTOS_STDINT */
|
||||
@@ -1,866 +0,0 @@
|
||||
/* Copyright 2018 Canaan Inc.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* http://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.
|
||||
*/
|
||||
/*
|
||||
* FreeRTOS Kernel V10.0.1
|
||||
* Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* http://www.FreeRTOS.org
|
||||
* http://aws.amazon.com/freertos
|
||||
*
|
||||
* 1 tab == 4 spaces!
|
||||
*/
|
||||
|
||||
/*
|
||||
* Stream buffers are used to send a continuous stream of data from one task or
|
||||
* interrupt to another. Their implementation is light weight, making them
|
||||
* particularly suited for interrupt to task and core to core communication
|
||||
* scenarios.
|
||||
*
|
||||
* ***NOTE***: Uniquely among FreeRTOS objects, the stream buffer
|
||||
* implementation (so also the message buffer implementation, as message buffers
|
||||
* are built on top of stream buffers) assumes there is only one task or
|
||||
* interrupt that will write to the buffer (the writer), and only one task or
|
||||
* interrupt that will read from the buffer (the reader). It is safe for the
|
||||
* writer and reader to be different tasks or interrupts, but, unlike other
|
||||
* FreeRTOS objects, it is not safe to have multiple different writers or
|
||||
* multiple different readers. If there are to be multiple different writers
|
||||
* then the application writer must place each call to a writing API function
|
||||
* (such as xStreamBufferSend()) inside a critical section and set the send
|
||||
* block time to 0. Likewise, if there are to be multiple different readers
|
||||
* then the application writer must place each call to a reading API function
|
||||
* (such as xStreamBufferRead()) inside a critical section section and set the
|
||||
* receive block time to 0.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef STREAM_BUFFER_H
|
||||
#define STREAM_BUFFER_H
|
||||
|
||||
#if defined( __cplusplus )
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Type by which stream buffers are referenced. For example, a call to
|
||||
* xStreamBufferCreate() returns an StreamBufferHandle_t variable that can
|
||||
* then be used as a parameter to xStreamBufferSend(), xStreamBufferReceive(),
|
||||
* etc.
|
||||
*/
|
||||
typedef void * StreamBufferHandle_t;
|
||||
|
||||
|
||||
/**
|
||||
* message_buffer.h
|
||||
*
|
||||
<pre>
|
||||
StreamBufferHandle_t xStreamBufferCreate( size_t xBufferSizeBytes, size_t xTriggerLevelBytes );
|
||||
</pre>
|
||||
*
|
||||
* Creates a new stream buffer using dynamically allocated memory. See
|
||||
* xStreamBufferCreateStatic() for a version that uses statically allocated
|
||||
* memory (memory that is allocated at compile time).
|
||||
*
|
||||
* configSUPPORT_DYNAMIC_ALLOCATION must be set to 1 or left undefined in
|
||||
* FreeRTOSConfig.h for xStreamBufferCreate() to be available.
|
||||
*
|
||||
* @param xBufferSizeBytes The total number of bytes the stream buffer will be
|
||||
* able to hold at any one time.
|
||||
*
|
||||
* @param xTriggerLevelBytes The number of bytes that must be in the stream
|
||||
* buffer before a task that is blocked on the stream buffer to wait for data is
|
||||
* moved out of the blocked state. For example, if a task is blocked on a read
|
||||
* of an empty stream buffer that has a trigger level of 1 then the task will be
|
||||
* unblocked when a single byte is written to the buffer or the task's block
|
||||
* time expires. As another example, if a task is blocked on a read of an empty
|
||||
* stream buffer that has a trigger level of 10 then the task will not be
|
||||
* unblocked until the stream buffer contains at least 10 bytes or the task's
|
||||
* block time expires. If a reading task's block time expires before the
|
||||
* trigger level is reached then the task will still receive however many bytes
|
||||
* are actually available. Setting a trigger level of 0 will result in a
|
||||
* trigger level of 1 being used. It is not valid to specify a trigger level
|
||||
* that is greater than the buffer size.
|
||||
*
|
||||
* @return If NULL is returned, then the stream buffer cannot be created
|
||||
* because there is insufficient heap memory available for FreeRTOS to allocate
|
||||
* the stream buffer data structures and storage area. A non-NULL value being
|
||||
* returned indicates that the stream buffer has been created successfully -
|
||||
* the returned value should be stored as the handle to the created stream
|
||||
* buffer.
|
||||
*
|
||||
* Example use:
|
||||
<pre>
|
||||
|
||||
void vAFunction( void )
|
||||
{
|
||||
StreamBufferHandle_t xStreamBuffer;
|
||||
const size_t xStreamBufferSizeBytes = 100, xTriggerLevel = 10;
|
||||
|
||||
// Create a stream buffer that can hold 100 bytes. The memory used to hold
|
||||
// both the stream buffer structure and the data in the stream buffer is
|
||||
// allocated dynamically.
|
||||
xStreamBuffer = xStreamBufferCreate( xStreamBufferSizeBytes, xTriggerLevel );
|
||||
|
||||
if( xStreamBuffer == NULL )
|
||||
{
|
||||
// There was not enough heap memory space available to create the
|
||||
// stream buffer.
|
||||
}
|
||||
else
|
||||
{
|
||||
// The stream buffer was created successfully and can now be used.
|
||||
}
|
||||
}
|
||||
</pre>
|
||||
* \defgroup xStreamBufferCreate xStreamBufferCreate
|
||||
* \ingroup StreamBufferManagement
|
||||
*/
|
||||
#define xStreamBufferCreate( xBufferSizeBytes, xTriggerLevelBytes ) xStreamBufferGenericCreate( xBufferSizeBytes, xTriggerLevelBytes, pdFALSE )
|
||||
|
||||
/**
|
||||
* stream_buffer.h
|
||||
*
|
||||
<pre>
|
||||
StreamBufferHandle_t xStreamBufferCreateStatic( size_t xBufferSizeBytes,
|
||||
size_t xTriggerLevelBytes,
|
||||
uint8_t *pucStreamBufferStorageArea,
|
||||
StaticStreamBuffer_t *pxStaticStreamBuffer );
|
||||
</pre>
|
||||
* Creates a new stream buffer using statically allocated memory. See
|
||||
* xStreamBufferCreate() for a version that uses dynamically allocated memory.
|
||||
*
|
||||
* configSUPPORT_STATIC_ALLOCATION must be set to 1 in FreeRTOSConfig.h for
|
||||
* xStreamBufferCreateStatic() to be available.
|
||||
*
|
||||
* @param xBufferSizeBytes The size, in bytes, of the buffer pointed to by the
|
||||
* pucStreamBufferStorageArea parameter.
|
||||
*
|
||||
* @param xTriggerLevelBytes The number of bytes that must be in the stream
|
||||
* buffer before a task that is blocked on the stream buffer to wait for data is
|
||||
* moved out of the blocked state. For example, if a task is blocked on a read
|
||||
* of an empty stream buffer that has a trigger level of 1 then the task will be
|
||||
* unblocked when a single byte is written to the buffer or the task's block
|
||||
* time expires. As another example, if a task is blocked on a read of an empty
|
||||
* stream buffer that has a trigger level of 10 then the task will not be
|
||||
* unblocked until the stream buffer contains at least 10 bytes or the task's
|
||||
* block time expires. If a reading task's block time expires before the
|
||||
* trigger level is reached then the task will still receive however many bytes
|
||||
* are actually available. Setting a trigger level of 0 will result in a
|
||||
* trigger level of 1 being used. It is not valid to specify a trigger level
|
||||
* that is greater than the buffer size.
|
||||
*
|
||||
* @param pucStreamBufferStorageArea Must point to a uint8_t array that is at
|
||||
* least xBufferSizeBytes + 1 big. This is the array to which streams are
|
||||
* copied when they are written to the stream buffer.
|
||||
*
|
||||
* @param pxStaticStreamBuffer Must point to a variable of type
|
||||
* StaticStreamBuffer_t, which will be used to hold the stream buffer's data
|
||||
* structure.
|
||||
*
|
||||
* @return If the stream buffer is created successfully then a handle to the
|
||||
* created stream buffer is returned. If either pucStreamBufferStorageArea or
|
||||
* pxStaticstreamBuffer are NULL then NULL is returned.
|
||||
*
|
||||
* Example use:
|
||||
<pre>
|
||||
|
||||
// Used to dimension the array used to hold the streams. The available space
|
||||
// will actually be one less than this, so 999.
|
||||
#define STORAGE_SIZE_BYTES 1000
|
||||
|
||||
// Defines the memory that will actually hold the streams within the stream
|
||||
// buffer.
|
||||
static uint8_t ucStorageBuffer[ STORAGE_SIZE_BYTES ];
|
||||
|
||||
// The variable used to hold the stream buffer structure.
|
||||
StaticStreamBuffer_t xStreamBufferStruct;
|
||||
|
||||
void MyFunction( void )
|
||||
{
|
||||
StreamBufferHandle_t xStreamBuffer;
|
||||
const size_t xTriggerLevel = 1;
|
||||
|
||||
xStreamBuffer = xStreamBufferCreateStatic( sizeof( ucBufferStorage ),
|
||||
xTriggerLevel,
|
||||
ucBufferStorage,
|
||||
&xStreamBufferStruct );
|
||||
|
||||
// As neither the pucStreamBufferStorageArea or pxStaticStreamBuffer
|
||||
// parameters were NULL, xStreamBuffer will not be NULL, and can be used to
|
||||
// reference the created stream buffer in other stream buffer API calls.
|
||||
|
||||
// Other code that uses the stream buffer can go here.
|
||||
}
|
||||
|
||||
</pre>
|
||||
* \defgroup xStreamBufferCreateStatic xStreamBufferCreateStatic
|
||||
* \ingroup StreamBufferManagement
|
||||
*/
|
||||
#define xStreamBufferCreateStatic( xBufferSizeBytes, xTriggerLevelBytes, pucStreamBufferStorageArea, pxStaticStreamBuffer ) xStreamBufferGenericCreateStatic( xBufferSizeBytes, xTriggerLevelBytes, pdFALSE, pucStreamBufferStorageArea, pxStaticStreamBuffer )
|
||||
|
||||
/**
|
||||
* stream_buffer.h
|
||||
*
|
||||
<pre>
|
||||
size_t xStreamBufferSend( StreamBufferHandle_t xStreamBuffer,
|
||||
const void *pvTxData,
|
||||
size_t xDataLengthBytes,
|
||||
TickType_t xTicksToWait );
|
||||
<pre>
|
||||
*
|
||||
* Sends bytes to a stream buffer. The bytes are copied into the stream buffer.
|
||||
*
|
||||
* ***NOTE***: Uniquely among FreeRTOS objects, the stream buffer
|
||||
* implementation (so also the message buffer implementation, as message buffers
|
||||
* are built on top of stream buffers) assumes there is only one task or
|
||||
* interrupt that will write to the buffer (the writer), and only one task or
|
||||
* interrupt that will read from the buffer (the reader). It is safe for the
|
||||
* writer and reader to be different tasks or interrupts, but, unlike other
|
||||
* FreeRTOS objects, it is not safe to have multiple different writers or
|
||||
* multiple different readers. If there are to be multiple different writers
|
||||
* then the application writer must place each call to a writing API function
|
||||
* (such as xStreamBufferSend()) inside a critical section and set the send
|
||||
* block time to 0. Likewise, if there are to be multiple different readers
|
||||
* then the application writer must place each call to a reading API function
|
||||
* (such as xStreamBufferRead()) inside a critical section and set the receive
|
||||
* block time to 0.
|
||||
*
|
||||
* Use xStreamBufferSend() to write to a stream buffer from a task. Use
|
||||
* xStreamBufferSendFromISR() to write to a stream buffer from an interrupt
|
||||
* service routine (ISR).
|
||||
*
|
||||
* @param xStreamBuffer The handle of the stream buffer to which a stream is
|
||||
* being sent.
|
||||
*
|
||||
* @param pvTxData A pointer to the buffer that holds the bytes to be copied
|
||||
* into the stream buffer.
|
||||
*
|
||||
* @param xDataLengthBytes The maximum number of bytes to copy from pvTxData
|
||||
* into the stream buffer.
|
||||
*
|
||||
* @param xTicksToWait The maximum amount of time the task should remain in the
|
||||
* Blocked state to wait for enough space to become available in the stream
|
||||
* buffer, should the stream buffer contain too little space to hold the
|
||||
* another xDataLengthBytes bytes. The block time is specified in tick periods,
|
||||
* so the absolute time it represents is dependent on the tick frequency. The
|
||||
* macro pdMS_TO_TICKS() can be used to convert a time specified in milliseconds
|
||||
* into a time specified in ticks. Setting xTicksToWait to portMAX_DELAY will
|
||||
* cause the task to wait indefinitely (without timing out), provided
|
||||
* INCLUDE_vTaskSuspend is set to 1 in FreeRTOSConfig.h. If a task times out
|
||||
* before it can write all xDataLengthBytes into the buffer it will still write
|
||||
* as many bytes as possible. A task does not use any CPU time when it is in
|
||||
* the blocked state.
|
||||
*
|
||||
* @return The number of bytes written to the stream buffer. If a task times
|
||||
* out before it can write all xDataLengthBytes into the buffer it will still
|
||||
* write as many bytes as possible.
|
||||
*
|
||||
* Example use:
|
||||
<pre>
|
||||
void vAFunction( StreamBufferHandle_t xStreamBuffer )
|
||||
{
|
||||
size_t xBytesSent;
|
||||
uint8_t ucArrayToSend[] = { 0, 1, 2, 3 };
|
||||
char *pcStringToSend = "String to send";
|
||||
const TickType_t x100ms = pdMS_TO_TICKS( 100 );
|
||||
|
||||
// Send an array to the stream buffer, blocking for a maximum of 100ms to
|
||||
// wait for enough space to be available in the stream buffer.
|
||||
xBytesSent = xStreamBufferSend( xStreamBuffer, ( void * ) ucArrayToSend, sizeof( ucArrayToSend ), x100ms );
|
||||
|
||||
if( xBytesSent != sizeof( ucArrayToSend ) )
|
||||
{
|
||||
// The call to xStreamBufferSend() times out before there was enough
|
||||
// space in the buffer for the data to be written, but it did
|
||||
// successfully write xBytesSent bytes.
|
||||
}
|
||||
|
||||
// Send the string to the stream buffer. Return immediately if there is not
|
||||
// enough space in the buffer.
|
||||
xBytesSent = xStreamBufferSend( xStreamBuffer, ( void * ) pcStringToSend, strlen( pcStringToSend ), 0 );
|
||||
|
||||
if( xBytesSent != strlen( pcStringToSend ) )
|
||||
{
|
||||
// The entire string could not be added to the stream buffer because
|
||||
// there was not enough free space in the buffer, but xBytesSent bytes
|
||||
// were sent. Could try again to send the remaining bytes.
|
||||
}
|
||||
}
|
||||
</pre>
|
||||
* \defgroup xStreamBufferSend xStreamBufferSend
|
||||
* \ingroup StreamBufferManagement
|
||||
*/
|
||||
size_t xStreamBufferSend( StreamBufferHandle_t xStreamBuffer,
|
||||
const void *pvTxData,
|
||||
size_t xDataLengthBytes,
|
||||
TickType_t xTicksToWait ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/**
|
||||
* stream_buffer.h
|
||||
*
|
||||
<pre>
|
||||
size_t xStreamBufferSendFromISR( StreamBufferHandle_t xStreamBuffer,
|
||||
const void *pvTxData,
|
||||
size_t xDataLengthBytes,
|
||||
BaseType_t *pxHigherPriorityTaskWoken );
|
||||
<pre>
|
||||
*
|
||||
* Interrupt safe version of the API function that sends a stream of bytes to
|
||||
* the stream buffer.
|
||||
*
|
||||
* ***NOTE***: Uniquely among FreeRTOS objects, the stream buffer
|
||||
* implementation (so also the message buffer implementation, as message buffers
|
||||
* are built on top of stream buffers) assumes there is only one task or
|
||||
* interrupt that will write to the buffer (the writer), and only one task or
|
||||
* interrupt that will read from the buffer (the reader). It is safe for the
|
||||
* writer and reader to be different tasks or interrupts, but, unlike other
|
||||
* FreeRTOS objects, it is not safe to have multiple different writers or
|
||||
* multiple different readers. If there are to be multiple different writers
|
||||
* then the application writer must place each call to a writing API function
|
||||
* (such as xStreamBufferSend()) inside a critical section and set the send
|
||||
* block time to 0. Likewise, if there are to be multiple different readers
|
||||
* then the application writer must place each call to a reading API function
|
||||
* (such as xStreamBufferRead()) inside a critical section and set the receive
|
||||
* block time to 0.
|
||||
*
|
||||
* Use xStreamBufferSend() to write to a stream buffer from a task. Use
|
||||
* xStreamBufferSendFromISR() to write to a stream buffer from an interrupt
|
||||
* service routine (ISR).
|
||||
*
|
||||
* @param xStreamBuffer The handle of the stream buffer to which a stream is
|
||||
* being sent.
|
||||
*
|
||||
* @param pvTxData A pointer to the data that is to be copied into the stream
|
||||
* buffer.
|
||||
*
|
||||
* @param xDataLengthBytes The maximum number of bytes to copy from pvTxData
|
||||
* into the stream buffer.
|
||||
*
|
||||
* @param pxHigherPriorityTaskWoken It is possible that a stream buffer will
|
||||
* have a task blocked on it waiting for data. Calling
|
||||
* xStreamBufferSendFromISR() can make data available, and so cause a task that
|
||||
* was waiting for data to leave the Blocked state. If calling
|
||||
* xStreamBufferSendFromISR() causes a task to leave the Blocked state, and the
|
||||
* unblocked task has a priority higher than the currently executing task (the
|
||||
* task that was interrupted), then, internally, xStreamBufferSendFromISR()
|
||||
* will set *pxHigherPriorityTaskWoken to pdTRUE. If
|
||||
* xStreamBufferSendFromISR() sets this value to pdTRUE, then normally a
|
||||
* context switch should be performed before the interrupt is exited. This will
|
||||
* ensure that the interrupt returns directly to the highest priority Ready
|
||||
* state task. *pxHigherPriorityTaskWoken should be set to pdFALSE before it
|
||||
* is passed into the function. See the example code below for an example.
|
||||
*
|
||||
* @return The number of bytes actually written to the stream buffer, which will
|
||||
* be less than xDataLengthBytes if the stream buffer didn't have enough free
|
||||
* space for all the bytes to be written.
|
||||
*
|
||||
* Example use:
|
||||
<pre>
|
||||
// A stream buffer that has already been created.
|
||||
StreamBufferHandle_t xStreamBuffer;
|
||||
|
||||
void vAnInterruptServiceRoutine( void )
|
||||
{
|
||||
size_t xBytesSent;
|
||||
char *pcStringToSend = "String to send";
|
||||
BaseType_t xHigherPriorityTaskWoken = pdFALSE; // Initialised to pdFALSE.
|
||||
|
||||
// Attempt to send the string to the stream buffer.
|
||||
xBytesSent = xStreamBufferSendFromISR( xStreamBuffer,
|
||||
( void * ) pcStringToSend,
|
||||
strlen( pcStringToSend ),
|
||||
&xHigherPriorityTaskWoken );
|
||||
|
||||
if( xBytesSent != strlen( pcStringToSend ) )
|
||||
{
|
||||
// There was not enough free space in the stream buffer for the entire
|
||||
// string to be written, ut xBytesSent bytes were written.
|
||||
}
|
||||
|
||||
// If xHigherPriorityTaskWoken was set to pdTRUE inside
|
||||
// xStreamBufferSendFromISR() then a task that has a priority above the
|
||||
// priority of the currently executing task was unblocked and a context
|
||||
// switch should be performed to ensure the ISR returns to the unblocked
|
||||
// task. In most FreeRTOS ports this is done by simply passing
|
||||
// xHigherPriorityTaskWoken into taskYIELD_FROM_ISR(), which will test the
|
||||
// variables value, and perform the context switch if necessary. Check the
|
||||
// documentation for the port in use for port specific instructions.
|
||||
taskYIELD_FROM_ISR( xHigherPriorityTaskWoken );
|
||||
}
|
||||
</pre>
|
||||
* \defgroup xStreamBufferSendFromISR xStreamBufferSendFromISR
|
||||
* \ingroup StreamBufferManagement
|
||||
*/
|
||||
size_t xStreamBufferSendFromISR( StreamBufferHandle_t xStreamBuffer,
|
||||
const void *pvTxData,
|
||||
size_t xDataLengthBytes,
|
||||
BaseType_t * const pxHigherPriorityTaskWoken ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/**
|
||||
* stream_buffer.h
|
||||
*
|
||||
<pre>
|
||||
size_t xStreamBufferReceive( StreamBufferHandle_t xStreamBuffer,
|
||||
void *pvRxData,
|
||||
size_t xBufferLengthBytes,
|
||||
TickType_t xTicksToWait );
|
||||
</pre>
|
||||
*
|
||||
* Receives bytes from a stream buffer.
|
||||
*
|
||||
* ***NOTE***: Uniquely among FreeRTOS objects, the stream buffer
|
||||
* implementation (so also the message buffer implementation, as message buffers
|
||||
* are built on top of stream buffers) assumes there is only one task or
|
||||
* interrupt that will write to the buffer (the writer), and only one task or
|
||||
* interrupt that will read from the buffer (the reader). It is safe for the
|
||||
* writer and reader to be different tasks or interrupts, but, unlike other
|
||||
* FreeRTOS objects, it is not safe to have multiple different writers or
|
||||
* multiple different readers. If there are to be multiple different writers
|
||||
* then the application writer must place each call to a writing API function
|
||||
* (such as xStreamBufferSend()) inside a critical section and set the send
|
||||
* block time to 0. Likewise, if there are to be multiple different readers
|
||||
* then the application writer must place each call to a reading API function
|
||||
* (such as xStreamBufferRead()) inside a critical section and set the receive
|
||||
* block time to 0.
|
||||
*
|
||||
* Use xStreamBufferReceive() to read from a stream buffer from a task. Use
|
||||
* xStreamBufferReceiveFromISR() to read from a stream buffer from an
|
||||
* interrupt service routine (ISR).
|
||||
*
|
||||
* @param xStreamBuffer The handle of the stream buffer from which bytes are to
|
||||
* be received.
|
||||
*
|
||||
* @param pvRxData A pointer to the buffer into which the received bytes will be
|
||||
* copied.
|
||||
*
|
||||
* @param xBufferLengthBytes The length of the buffer pointed to by the
|
||||
* pvRxData parameter. This sets the maximum number of bytes to receive in one
|
||||
* call. xStreamBufferReceive will return as many bytes as possible up to a
|
||||
* maximum set by xBufferLengthBytes.
|
||||
*
|
||||
* @param xTicksToWait The maximum amount of time the task should remain in the
|
||||
* Blocked state to wait for data to become available if the stream buffer is
|
||||
* empty. xStreamBufferReceive() will return immediately if xTicksToWait is
|
||||
* zero. The block time is specified in tick periods, so the absolute time it
|
||||
* represents is dependent on the tick frequency. The macro pdMS_TO_TICKS() can
|
||||
* be used to convert a time specified in milliseconds into a time specified in
|
||||
* ticks. Setting xTicksToWait to portMAX_DELAY will cause the task to wait
|
||||
* indefinitely (without timing out), provided INCLUDE_vTaskSuspend is set to 1
|
||||
* in FreeRTOSConfig.h. A task does not use any CPU time when it is in the
|
||||
* Blocked state.
|
||||
*
|
||||
* @return The number of bytes actually read from the stream buffer, which will
|
||||
* be less than xBufferLengthBytes if the call to xStreamBufferReceive() timed
|
||||
* out before xBufferLengthBytes were available.
|
||||
*
|
||||
* Example use:
|
||||
<pre>
|
||||
void vAFunction( StreamBuffer_t xStreamBuffer )
|
||||
{
|
||||
uint8_t ucRxData[ 20 ];
|
||||
size_t xReceivedBytes;
|
||||
const TickType_t xBlockTime = pdMS_TO_TICKS( 20 );
|
||||
|
||||
// Receive up to another sizeof( ucRxData ) bytes from the stream buffer.
|
||||
// Wait in the Blocked state (so not using any CPU processing time) for a
|
||||
// maximum of 100ms for the full sizeof( ucRxData ) number of bytes to be
|
||||
// available.
|
||||
xReceivedBytes = xStreamBufferReceive( xStreamBuffer,
|
||||
( void * ) ucRxData,
|
||||
sizeof( ucRxData ),
|
||||
xBlockTime );
|
||||
|
||||
if( xReceivedBytes > 0 )
|
||||
{
|
||||
// A ucRxData contains another xRecievedBytes bytes of data, which can
|
||||
// be processed here....
|
||||
}
|
||||
}
|
||||
</pre>
|
||||
* \defgroup xStreamBufferReceive xStreamBufferReceive
|
||||
* \ingroup StreamBufferManagement
|
||||
*/
|
||||
size_t xStreamBufferReceive( StreamBufferHandle_t xStreamBuffer,
|
||||
void *pvRxData,
|
||||
size_t xBufferLengthBytes,
|
||||
TickType_t xTicksToWait ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/**
|
||||
* stream_buffer.h
|
||||
*
|
||||
<pre>
|
||||
size_t xStreamBufferReceiveFromISR( StreamBufferHandle_t xStreamBuffer,
|
||||
void *pvRxData,
|
||||
size_t xBufferLengthBytes,
|
||||
BaseType_t *pxHigherPriorityTaskWoken );
|
||||
</pre>
|
||||
*
|
||||
* An interrupt safe version of the API function that receives bytes from a
|
||||
* stream buffer.
|
||||
*
|
||||
* Use xStreamBufferReceive() to read bytes from a stream buffer from a task.
|
||||
* Use xStreamBufferReceiveFromISR() to read bytes from a stream buffer from an
|
||||
* interrupt service routine (ISR).
|
||||
*
|
||||
* @param xStreamBuffer The handle of the stream buffer from which a stream
|
||||
* is being received.
|
||||
*
|
||||
* @param pvRxData A pointer to the buffer into which the received bytes are
|
||||
* copied.
|
||||
*
|
||||
* @param xBufferLengthBytes The length of the buffer pointed to by the
|
||||
* pvRxData parameter. This sets the maximum number of bytes to receive in one
|
||||
* call. xStreamBufferReceive will return as many bytes as possible up to a
|
||||
* maximum set by xBufferLengthBytes.
|
||||
*
|
||||
* @param pxHigherPriorityTaskWoken It is possible that a stream buffer will
|
||||
* have a task blocked on it waiting for space to become available. Calling
|
||||
* xStreamBufferReceiveFromISR() can make space available, and so cause a task
|
||||
* that is waiting for space to leave the Blocked state. If calling
|
||||
* xStreamBufferReceiveFromISR() causes a task to leave the Blocked state, and
|
||||
* the unblocked task has a priority higher than the currently executing task
|
||||
* (the task that was interrupted), then, internally,
|
||||
* xStreamBufferReceiveFromISR() will set *pxHigherPriorityTaskWoken to pdTRUE.
|
||||
* If xStreamBufferReceiveFromISR() sets this value to pdTRUE, then normally a
|
||||
* context switch should be performed before the interrupt is exited. That will
|
||||
* ensure the interrupt returns directly to the highest priority Ready state
|
||||
* task. *pxHigherPriorityTaskWoken should be set to pdFALSE before it is
|
||||
* passed into the function. See the code example below for an example.
|
||||
*
|
||||
* @return The number of bytes read from the stream buffer, if any.
|
||||
*
|
||||
* Example use:
|
||||
<pre>
|
||||
// A stream buffer that has already been created.
|
||||
StreamBuffer_t xStreamBuffer;
|
||||
|
||||
void vAnInterruptServiceRoutine( void )
|
||||
{
|
||||
uint8_t ucRxData[ 20 ];
|
||||
size_t xReceivedBytes;
|
||||
BaseType_t xHigherPriorityTaskWoken = pdFALSE; // Initialised to pdFALSE.
|
||||
|
||||
// Receive the next stream from the stream buffer.
|
||||
xReceivedBytes = xStreamBufferReceiveFromISR( xStreamBuffer,
|
||||
( void * ) ucRxData,
|
||||
sizeof( ucRxData ),
|
||||
&xHigherPriorityTaskWoken );
|
||||
|
||||
if( xReceivedBytes > 0 )
|
||||
{
|
||||
// ucRxData contains xReceivedBytes read from the stream buffer.
|
||||
// Process the stream here....
|
||||
}
|
||||
|
||||
// If xHigherPriorityTaskWoken was set to pdTRUE inside
|
||||
// xStreamBufferReceiveFromISR() then a task that has a priority above the
|
||||
// priority of the currently executing task was unblocked and a context
|
||||
// switch should be performed to ensure the ISR returns to the unblocked
|
||||
// task. In most FreeRTOS ports this is done by simply passing
|
||||
// xHigherPriorityTaskWoken into taskYIELD_FROM_ISR(), which will test the
|
||||
// variables value, and perform the context switch if necessary. Check the
|
||||
// documentation for the port in use for port specific instructions.
|
||||
taskYIELD_FROM_ISR( xHigherPriorityTaskWoken );
|
||||
}
|
||||
</pre>
|
||||
* \defgroup xStreamBufferReceiveFromISR xStreamBufferReceiveFromISR
|
||||
* \ingroup StreamBufferManagement
|
||||
*/
|
||||
size_t xStreamBufferReceiveFromISR( StreamBufferHandle_t xStreamBuffer,
|
||||
void *pvRxData,
|
||||
size_t xBufferLengthBytes,
|
||||
BaseType_t * const pxHigherPriorityTaskWoken ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/**
|
||||
* stream_buffer.h
|
||||
*
|
||||
<pre>
|
||||
void vStreamBufferDelete( StreamBufferHandle_t xStreamBuffer );
|
||||
</pre>
|
||||
*
|
||||
* Deletes a stream buffer that was previously created using a call to
|
||||
* xStreamBufferCreate() or xStreamBufferCreateStatic(). If the stream
|
||||
* buffer was created using dynamic memory (that is, by xStreamBufferCreate()),
|
||||
* then the allocated memory is freed.
|
||||
*
|
||||
* A stream buffer handle must not be used after the stream buffer has been
|
||||
* deleted.
|
||||
*
|
||||
* @param xStreamBuffer The handle of the stream buffer to be deleted.
|
||||
*
|
||||
* \defgroup vStreamBufferDelete vStreamBufferDelete
|
||||
* \ingroup StreamBufferManagement
|
||||
*/
|
||||
void vStreamBufferDelete( StreamBufferHandle_t xStreamBuffer ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/**
|
||||
* stream_buffer.h
|
||||
*
|
||||
<pre>
|
||||
BaseType_t xStreamBufferIsFull( StreamBufferHandle_t xStreamBuffer );
|
||||
</pre>
|
||||
*
|
||||
* Queries a stream buffer to see if it is full. A stream buffer is full if it
|
||||
* does not have any free space, and therefore cannot accept any more data.
|
||||
*
|
||||
* @param xStreamBuffer The handle of the stream buffer being queried.
|
||||
*
|
||||
* @return If the stream buffer is full then pdTRUE is returned. Otherwise
|
||||
* pdFALSE is returned.
|
||||
*
|
||||
* \defgroup xStreamBufferIsFull xStreamBufferIsFull
|
||||
* \ingroup StreamBufferManagement
|
||||
*/
|
||||
BaseType_t xStreamBufferIsFull( StreamBufferHandle_t xStreamBuffer ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/**
|
||||
* stream_buffer.h
|
||||
*
|
||||
<pre>
|
||||
BaseType_t xStreamBufferIsEmpty( StreamBufferHandle_t xStreamBuffer );
|
||||
</pre>
|
||||
*
|
||||
* Queries a stream buffer to see if it is empty. A stream buffer is empty if
|
||||
* it does not contain any data.
|
||||
*
|
||||
* @param xStreamBuffer The handle of the stream buffer being queried.
|
||||
*
|
||||
* @return If the stream buffer is empty then pdTRUE is returned. Otherwise
|
||||
* pdFALSE is returned.
|
||||
*
|
||||
* \defgroup xStreamBufferIsEmpty xStreamBufferIsEmpty
|
||||
* \ingroup StreamBufferManagement
|
||||
*/
|
||||
BaseType_t xStreamBufferIsEmpty( StreamBufferHandle_t xStreamBuffer ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/**
|
||||
* stream_buffer.h
|
||||
*
|
||||
<pre>
|
||||
BaseType_t xStreamBufferReset( StreamBufferHandle_t xStreamBuffer );
|
||||
</pre>
|
||||
*
|
||||
* Resets a stream buffer to its initial, empty, state. Any data that was in
|
||||
* the stream buffer is discarded. A stream buffer can only be reset if there
|
||||
* are no tasks blocked waiting to either send to or receive from the stream
|
||||
* buffer.
|
||||
*
|
||||
* @param xStreamBuffer The handle of the stream buffer being reset.
|
||||
*
|
||||
* @return If the stream buffer is reset then pdPASS is returned. If there was
|
||||
* a task blocked waiting to send to or read from the stream buffer then the
|
||||
* stream buffer is not reset and pdFAIL is returned.
|
||||
*
|
||||
* \defgroup xStreamBufferReset xStreamBufferReset
|
||||
* \ingroup StreamBufferManagement
|
||||
*/
|
||||
BaseType_t xStreamBufferReset( StreamBufferHandle_t xStreamBuffer ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/**
|
||||
* stream_buffer.h
|
||||
*
|
||||
<pre>
|
||||
size_t xStreamBufferSpacesAvailable( StreamBufferHandle_t xStreamBuffer );
|
||||
</pre>
|
||||
*
|
||||
* Queries a stream buffer to see how much free space it contains, which is
|
||||
* equal to the amount of data that can be sent to the stream buffer before it
|
||||
* is full.
|
||||
*
|
||||
* @param xStreamBuffer The handle of the stream buffer being queried.
|
||||
*
|
||||
* @return The number of bytes that can be written to the stream buffer before
|
||||
* the stream buffer would be full.
|
||||
*
|
||||
* \defgroup xStreamBufferSpacesAvailable xStreamBufferSpacesAvailable
|
||||
* \ingroup StreamBufferManagement
|
||||
*/
|
||||
size_t xStreamBufferSpacesAvailable( StreamBufferHandle_t xStreamBuffer ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/**
|
||||
* stream_buffer.h
|
||||
*
|
||||
<pre>
|
||||
size_t xStreamBufferBytesAvailable( StreamBufferHandle_t xStreamBuffer );
|
||||
</pre>
|
||||
*
|
||||
* Queries a stream buffer to see how much data it contains, which is equal to
|
||||
* the number of bytes that can be read from the stream buffer before the stream
|
||||
* buffer would be empty.
|
||||
*
|
||||
* @param xStreamBuffer The handle of the stream buffer being queried.
|
||||
*
|
||||
* @return The number of bytes that can be read from the stream buffer before
|
||||
* the stream buffer would be empty.
|
||||
*
|
||||
* \defgroup xStreamBufferBytesAvailable xStreamBufferBytesAvailable
|
||||
* \ingroup StreamBufferManagement
|
||||
*/
|
||||
size_t xStreamBufferBytesAvailable( StreamBufferHandle_t xStreamBuffer ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/**
|
||||
* stream_buffer.h
|
||||
*
|
||||
<pre>
|
||||
BaseType_t xStreamBufferSetTriggerLevel( StreamBufferHandle_t xStreamBuffer, size_t xTriggerLevel );
|
||||
</pre>
|
||||
*
|
||||
* A stream buffer's trigger level is the number of bytes that must be in the
|
||||
* stream buffer before a task that is blocked on the stream buffer to
|
||||
* wait for data is moved out of the blocked state. For example, if a task is
|
||||
* blocked on a read of an empty stream buffer that has a trigger level of 1
|
||||
* then the task will be unblocked when a single byte is written to the buffer
|
||||
* or the task's block time expires. As another example, if a task is blocked
|
||||
* on a read of an empty stream buffer that has a trigger level of 10 then the
|
||||
* task will not be unblocked until the stream buffer contains at least 10 bytes
|
||||
* or the task's block time expires. If a reading task's block time expires
|
||||
* before the trigger level is reached then the task will still receive however
|
||||
* many bytes are actually available. Setting a trigger level of 0 will result
|
||||
* in a trigger level of 1 being used. It is not valid to specify a trigger
|
||||
* level that is greater than the buffer size.
|
||||
*
|
||||
* A trigger level is set when the stream buffer is created, and can be modified
|
||||
* using xStreamBufferSetTriggerLevel().
|
||||
*
|
||||
* @param xStreamBuffer The handle of the stream buffer being updated.
|
||||
*
|
||||
* @param xTriggerLevel The new trigger level for the stream buffer.
|
||||
*
|
||||
* @return If xTriggerLevel was less than or equal to the stream buffer's length
|
||||
* then the trigger level will be updated and pdTRUE is returned. Otherwise
|
||||
* pdFALSE is returned.
|
||||
*
|
||||
* \defgroup xStreamBufferSetTriggerLevel xStreamBufferSetTriggerLevel
|
||||
* \ingroup StreamBufferManagement
|
||||
*/
|
||||
BaseType_t xStreamBufferSetTriggerLevel( StreamBufferHandle_t xStreamBuffer, size_t xTriggerLevel ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/**
|
||||
* stream_buffer.h
|
||||
*
|
||||
<pre>
|
||||
BaseType_t xStreamBufferSendCompletedFromISR( StreamBufferHandle_t xStreamBuffer, BaseType_t *pxHigherPriorityTaskWoken );
|
||||
</pre>
|
||||
*
|
||||
* For advanced users only.
|
||||
*
|
||||
* The sbSEND_COMPLETED() macro is called from within the FreeRTOS APIs when
|
||||
* data is sent to a message buffer or stream buffer. If there was a task that
|
||||
* was blocked on the message or stream buffer waiting for data to arrive then
|
||||
* the sbSEND_COMPLETED() macro sends a notification to the task to remove it
|
||||
* from the Blocked state. xStreamBufferSendCompletedFromISR() does the same
|
||||
* thing. It is provided to enable application writers to implement their own
|
||||
* version of sbSEND_COMPLETED(), and MUST NOT BE USED AT ANY OTHER TIME.
|
||||
*
|
||||
* See the example implemented in FreeRTOS/Demo/Minimal/MessageBufferAMP.c for
|
||||
* additional information.
|
||||
*
|
||||
* @param xStreamBuffer The handle of the stream buffer to which data was
|
||||
* written.
|
||||
*
|
||||
* @param pxHigherPriorityTaskWoken *pxHigherPriorityTaskWoken should be
|
||||
* initialised to pdFALSE before it is passed into
|
||||
* xStreamBufferSendCompletedFromISR(). If calling
|
||||
* xStreamBufferSendCompletedFromISR() removes a task from the Blocked state,
|
||||
* and the task has a priority above the priority of the currently running task,
|
||||
* then *pxHigherPriorityTaskWoken will get set to pdTRUE indicating that a
|
||||
* context switch should be performed before exiting the ISR.
|
||||
*
|
||||
* @return If a task was removed from the Blocked state then pdTRUE is returned.
|
||||
* Otherwise pdFALSE is returned.
|
||||
*
|
||||
* \defgroup xStreamBufferSendCompletedFromISR xStreamBufferSendCompletedFromISR
|
||||
* \ingroup StreamBufferManagement
|
||||
*/
|
||||
BaseType_t xStreamBufferSendCompletedFromISR( StreamBufferHandle_t xStreamBuffer, BaseType_t *pxHigherPriorityTaskWoken ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/**
|
||||
* stream_buffer.h
|
||||
*
|
||||
<pre>
|
||||
BaseType_t xStreamBufferReceiveCompletedFromISR( StreamBufferHandle_t xStreamBuffer, BaseType_t *pxHigherPriorityTaskWoken );
|
||||
</pre>
|
||||
*
|
||||
* For advanced users only.
|
||||
*
|
||||
* The sbRECEIVE_COMPLETED() macro is called from within the FreeRTOS APIs when
|
||||
* data is read out of a message buffer or stream buffer. If there was a task
|
||||
* that was blocked on the message or stream buffer waiting for data to arrive
|
||||
* then the sbRECEIVE_COMPLETED() macro sends a notification to the task to
|
||||
* remove it from the Blocked state. xStreamBufferReceiveCompletedFromISR()
|
||||
* does the same thing. It is provided to enable application writers to
|
||||
* implement their own version of sbRECEIVE_COMPLETED(), and MUST NOT BE USED AT
|
||||
* ANY OTHER TIME.
|
||||
*
|
||||
* See the example implemented in FreeRTOS/Demo/Minimal/MessageBufferAMP.c for
|
||||
* additional information.
|
||||
*
|
||||
* @param xStreamBuffer The handle of the stream buffer from which data was
|
||||
* read.
|
||||
*
|
||||
* @param pxHigherPriorityTaskWoken *pxHigherPriorityTaskWoken should be
|
||||
* initialised to pdFALSE before it is passed into
|
||||
* xStreamBufferReceiveCompletedFromISR(). If calling
|
||||
* xStreamBufferReceiveCompletedFromISR() removes a task from the Blocked state,
|
||||
* and the task has a priority above the priority of the currently running task,
|
||||
* then *pxHigherPriorityTaskWoken will get set to pdTRUE indicating that a
|
||||
* context switch should be performed before exiting the ISR.
|
||||
*
|
||||
* @return If a task was removed from the Blocked state then pdTRUE is returned.
|
||||
* Otherwise pdFALSE is returned.
|
||||
*
|
||||
* \defgroup xStreamBufferReceiveCompletedFromISR xStreamBufferReceiveCompletedFromISR
|
||||
* \ingroup StreamBufferManagement
|
||||
*/
|
||||
BaseType_t xStreamBufferReceiveCompletedFromISR( StreamBufferHandle_t xStreamBuffer, BaseType_t *pxHigherPriorityTaskWoken ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/* Functions below here are not part of the public API. */
|
||||
StreamBufferHandle_t xStreamBufferGenericCreate( size_t xBufferSizeBytes,
|
||||
size_t xTriggerLevelBytes,
|
||||
BaseType_t xIsMessageBuffer ) PRIVILEGED_FUNCTION;
|
||||
|
||||
StreamBufferHandle_t xStreamBufferGenericCreateStatic( size_t xBufferSizeBytes,
|
||||
size_t xTriggerLevelBytes,
|
||||
BaseType_t xIsMessageBuffer,
|
||||
uint8_t * const pucStreamBufferStorageArea,
|
||||
StaticStreamBuffer_t * const pxStaticStreamBuffer ) PRIVILEGED_FUNCTION;
|
||||
|
||||
#if( configUSE_TRACE_FACILITY == 1 )
|
||||
void vStreamBufferSetStreamBufferNumber( StreamBufferHandle_t xStreamBuffer, UBaseType_t uxStreamBufferNumber ) PRIVILEGED_FUNCTION;
|
||||
UBaseType_t uxStreamBufferGetStreamBufferNumber( StreamBufferHandle_t xStreamBuffer ) PRIVILEGED_FUNCTION;
|
||||
uint8_t ucStreamBufferGetStreamBufferType( StreamBufferHandle_t xStreamBuffer ) PRIVILEGED_FUNCTION;
|
||||
#endif
|
||||
|
||||
#if defined( __cplusplus )
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* !defined( STREAM_BUFFER_H ) */
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,212 +0,0 @@
|
||||
/* Copyright 2018 Canaan Inc.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* http://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.
|
||||
*/
|
||||
/*
|
||||
* FreeRTOS Kernel V10.0.1
|
||||
* Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* http://www.FreeRTOS.org
|
||||
* http://aws.amazon.com/freertos
|
||||
*
|
||||
* 1 tab == 4 spaces!
|
||||
*/
|
||||
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "FreeRTOS.h"
|
||||
#include "list.h"
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* PUBLIC LIST API documented in list.h
|
||||
*----------------------------------------------------------*/
|
||||
|
||||
void vListInitialise( List_t * const pxList )
|
||||
{
|
||||
/* The list structure contains a list item which is used to mark the
|
||||
end of the list. To initialise the list the list end is inserted
|
||||
as the only list entry. */
|
||||
pxList->pxIndex = ( ListItem_t * ) &( pxList->xListEnd ); /*lint !e826 !e740 The mini list structure is used as the list end to save RAM. This is checked and valid. */
|
||||
|
||||
/* The list end value is the highest possible value in the list to
|
||||
ensure it remains at the end of the list. */
|
||||
pxList->xListEnd.xItemValue = portMAX_DELAY;
|
||||
|
||||
/* The list end next and previous pointers point to itself so we know
|
||||
when the list is empty. */
|
||||
pxList->xListEnd.pxNext = ( ListItem_t * ) &( pxList->xListEnd ); /*lint !e826 !e740 The mini list structure is used as the list end to save RAM. This is checked and valid. */
|
||||
pxList->xListEnd.pxPrevious = ( ListItem_t * ) &( pxList->xListEnd );/*lint !e826 !e740 The mini list structure is used as the list end to save RAM. This is checked and valid. */
|
||||
|
||||
pxList->uxNumberOfItems = ( UBaseType_t ) 0U;
|
||||
|
||||
/* Write known values into the list if
|
||||
configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */
|
||||
listSET_LIST_INTEGRITY_CHECK_1_VALUE( pxList );
|
||||
listSET_LIST_INTEGRITY_CHECK_2_VALUE( pxList );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vListInitialiseItem( ListItem_t * const pxItem )
|
||||
{
|
||||
/* Make sure the list item is not recorded as being on a list. */
|
||||
pxItem->pvContainer = NULL;
|
||||
|
||||
/* Write known values into the list item if
|
||||
configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */
|
||||
listSET_FIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxItem );
|
||||
listSET_SECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxItem );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vListInsertEnd( List_t * const pxList, ListItem_t * const pxNewListItem )
|
||||
{
|
||||
ListItem_t * const pxIndex = pxList->pxIndex;
|
||||
|
||||
/* Only effective when configASSERT() is also defined, these tests may catch
|
||||
the list data structures being overwritten in memory. They will not catch
|
||||
data errors caused by incorrect configuration or use of FreeRTOS. */
|
||||
listTEST_LIST_INTEGRITY( pxList );
|
||||
listTEST_LIST_ITEM_INTEGRITY( pxNewListItem );
|
||||
|
||||
/* Insert a new list item into pxList, but rather than sort the list,
|
||||
makes the new list item the last item to be removed by a call to
|
||||
listGET_OWNER_OF_NEXT_ENTRY(). */
|
||||
pxNewListItem->pxNext = pxIndex;
|
||||
pxNewListItem->pxPrevious = pxIndex->pxPrevious;
|
||||
|
||||
/* Only used during decision coverage testing. */
|
||||
mtCOVERAGE_TEST_DELAY();
|
||||
|
||||
pxIndex->pxPrevious->pxNext = pxNewListItem;
|
||||
pxIndex->pxPrevious = pxNewListItem;
|
||||
|
||||
/* Remember which list the item is in. */
|
||||
pxNewListItem->pvContainer = ( void * ) pxList;
|
||||
|
||||
( pxList->uxNumberOfItems )++;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vListInsert( List_t * const pxList, ListItem_t * const pxNewListItem )
|
||||
{
|
||||
ListItem_t *pxIterator;
|
||||
const TickType_t xValueOfInsertion = pxNewListItem->xItemValue;
|
||||
|
||||
/* Only effective when configASSERT() is also defined, these tests may catch
|
||||
the list data structures being overwritten in memory. They will not catch
|
||||
data errors caused by incorrect configuration or use of FreeRTOS. */
|
||||
listTEST_LIST_INTEGRITY( pxList );
|
||||
listTEST_LIST_ITEM_INTEGRITY( pxNewListItem );
|
||||
|
||||
/* Insert the new list item into the list, sorted in xItemValue order.
|
||||
|
||||
If the list already contains a list item with the same item value then the
|
||||
new list item should be placed after it. This ensures that TCB's which are
|
||||
stored in ready lists (all of which have the same xItemValue value) get a
|
||||
share of the CPU. However, if the xItemValue is the same as the back marker
|
||||
the iteration loop below will not end. Therefore the value is checked
|
||||
first, and the algorithm slightly modified if necessary. */
|
||||
if( xValueOfInsertion == portMAX_DELAY )
|
||||
{
|
||||
pxIterator = pxList->xListEnd.pxPrevious;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* *** NOTE ***********************************************************
|
||||
If you find your application is crashing here then likely causes are
|
||||
listed below. In addition see http://www.freertos.org/FAQHelp.html for
|
||||
more tips, and ensure configASSERT() is defined!
|
||||
http://www.freertos.org/a00110.html#configASSERT
|
||||
|
||||
1) Stack overflow -
|
||||
see http://www.freertos.org/Stacks-and-stack-overflow-checking.html
|
||||
2) Incorrect interrupt priority assignment, especially on Cortex-M
|
||||
parts where numerically high priority values denote low actual
|
||||
interrupt priorities, which can seem counter intuitive. See
|
||||
http://www.freertos.org/RTOS-Cortex-M3-M4.html and the definition
|
||||
of configMAX_SYSCALL_INTERRUPT_PRIORITY on
|
||||
http://www.freertos.org/a00110.html
|
||||
3) Calling an API function from within a critical section or when
|
||||
the scheduler is suspended, or calling an API function that does
|
||||
not end in "FromISR" from an interrupt.
|
||||
4) Using a queue or semaphore before it has been initialised or
|
||||
before the scheduler has been started (are interrupts firing
|
||||
before vTaskStartScheduler() has been called?).
|
||||
**********************************************************************/
|
||||
|
||||
for( pxIterator = ( ListItem_t * ) &( pxList->xListEnd ); pxIterator->pxNext->xItemValue <= xValueOfInsertion; pxIterator = pxIterator->pxNext ) /*lint !e826 !e740 The mini list structure is used as the list end to save RAM. This is checked and valid. */
|
||||
{
|
||||
/* There is nothing to do here, just iterating to the wanted
|
||||
insertion position. */
|
||||
}
|
||||
}
|
||||
|
||||
pxNewListItem->pxNext = pxIterator->pxNext;
|
||||
pxNewListItem->pxNext->pxPrevious = pxNewListItem;
|
||||
pxNewListItem->pxPrevious = pxIterator;
|
||||
pxIterator->pxNext = pxNewListItem;
|
||||
|
||||
/* Remember which list the item is in. This allows fast removal of the
|
||||
item later. */
|
||||
pxNewListItem->pvContainer = ( void * ) pxList;
|
||||
|
||||
( pxList->uxNumberOfItems )++;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
UBaseType_t uxListRemove( ListItem_t * const pxItemToRemove )
|
||||
{
|
||||
/* The list item knows which list it is in. Obtain the list from the list
|
||||
item. */
|
||||
List_t * const pxList = ( List_t * ) pxItemToRemove->pvContainer;
|
||||
|
||||
pxItemToRemove->pxNext->pxPrevious = pxItemToRemove->pxPrevious;
|
||||
pxItemToRemove->pxPrevious->pxNext = pxItemToRemove->pxNext;
|
||||
|
||||
/* Only used during decision coverage testing. */
|
||||
mtCOVERAGE_TEST_DELAY();
|
||||
|
||||
/* Make sure the index is left pointing to a valid item. */
|
||||
if( pxList->pxIndex == pxItemToRemove )
|
||||
{
|
||||
pxList->pxIndex = pxItemToRemove->pxPrevious;
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
|
||||
pxItemToRemove->pvContainer = NULL;
|
||||
( pxList->uxNumberOfItems )--;
|
||||
|
||||
return pxList->uxNumberOfItems;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
@@ -1,48 +0,0 @@
|
||||
#include <sys/lock.h>
|
||||
#include <stdlib.h>
|
||||
#include "FreeRTOS.h"
|
||||
#include "semphr.h"
|
||||
#include "portmacro.h"
|
||||
#include "task.h"
|
||||
|
||||
typedef long _lock_t;
|
||||
|
||||
void _lock_init(_lock_t *lock)
|
||||
{
|
||||
}
|
||||
|
||||
void _lock_init_recursive(_lock_t *lock)
|
||||
{
|
||||
}
|
||||
|
||||
void _lock_close(_lock_t *lock)
|
||||
{
|
||||
}
|
||||
|
||||
void _lock_close_recursive(_lock_t *lock) __attribute__((alias("_lock_close")));
|
||||
|
||||
void _lock_acquire(_lock_t *lock)
|
||||
{
|
||||
}
|
||||
|
||||
void _lock_acquire_recursive(_lock_t *lock)
|
||||
{
|
||||
}
|
||||
|
||||
int _lock_try_acquire(_lock_t *lock)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
int _lock_try_acquire_recursive(_lock_t *lock)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
void _lock_release(_lock_t *lock)
|
||||
{
|
||||
}
|
||||
|
||||
void _lock_release_recursive(_lock_t *lock)
|
||||
{
|
||||
}
|
||||
@@ -1,49 +0,0 @@
|
||||
/* Copyright 2018 Canaan Inc.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* http://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.
|
||||
*/
|
||||
#include "FreeRTOS.h"
|
||||
#include "core_sync.h"
|
||||
#include "task.h"
|
||||
#include <clint.h>
|
||||
#include <encoding.h>
|
||||
#include <fpioa.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
static StaticTask_t s_idle_task;
|
||||
static StackType_t s_idle_task_stack[configMINIMAL_STACK_SIZE];
|
||||
|
||||
void vApplicationIdleHook(void)
|
||||
{
|
||||
}
|
||||
|
||||
void vApplicationGetIdleTaskMemory(StaticTask_t **ppxIdleTaskTCBBuffer, StackType_t **ppxIdleTaskStackBuffer, uint32_t *pulIdleTaskStackSize)
|
||||
{
|
||||
/* Pass out a pointer to the StaticTask_t structure in which the Idle task's
|
||||
state will be stored. */
|
||||
*ppxIdleTaskTCBBuffer = &s_idle_task;
|
||||
|
||||
/* Pass out the array that will be used as the Idle task's stack. */
|
||||
*ppxIdleTaskStackBuffer = s_idle_task_stack;
|
||||
|
||||
/* Pass out the size of the array pointed to by *ppxIdleTaskStackBuffer.
|
||||
Note that, as the array is necessarily of type StackType_t,
|
||||
configMINIMAL_STACK_SIZE is specified in words, not bytes. */
|
||||
*pulIdleTaskStackSize = configMINIMAL_STACK_SIZE;
|
||||
}
|
||||
|
||||
void vApplicationStackOverflowHook(TaskHandle_t xTask, char *pcTaskName)
|
||||
{
|
||||
configASSERT(!"Stackoverflow !");
|
||||
}
|
||||
@@ -1,451 +0,0 @@
|
||||
/* Copyright 2018 Canaan Inc.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* http://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.
|
||||
*/
|
||||
/*
|
||||
* FreeRTOS Kernel V10.0.1
|
||||
* Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* http://www.FreeRTOS.org
|
||||
* http://aws.amazon.com/freertos
|
||||
*
|
||||
* 1 tab == 4 spaces!
|
||||
*/
|
||||
|
||||
/*
|
||||
* A sample implementation of pvPortMalloc() and vPortFree() that combines
|
||||
* (coalescences) adjacent memory blocks as they are freed, and in so doing
|
||||
* limits memory fragmentation.
|
||||
*
|
||||
* See heap_1.c, heap_2.c and heap_3.c for alternative implementations, and the
|
||||
* memory management pages of http://www.FreeRTOS.org for more information.
|
||||
*/
|
||||
#include <stdlib.h>
|
||||
|
||||
/* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining
|
||||
all the API functions to use the MPU wrappers. That should only be done when
|
||||
task.h is included from an application file. */
|
||||
#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE
|
||||
|
||||
#include "atomic.h"
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
|
||||
#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE
|
||||
|
||||
#if( configSUPPORT_DYNAMIC_ALLOCATION == 0 )
|
||||
#error This file must not be used if configSUPPORT_DYNAMIC_ALLOCATION is 0
|
||||
#endif
|
||||
|
||||
/* Block sizes must not get too small. */
|
||||
#define heapMINIMUM_BLOCK_SIZE ( ( size_t ) ( xHeapStructSize << 1 ) )
|
||||
|
||||
/* Assumes 8bit bytes! */
|
||||
#define heapBITS_PER_BYTE ( ( size_t ) 8 )
|
||||
|
||||
/* Allocate the memory for the heap. */
|
||||
#if( configAPPLICATION_ALLOCATED_HEAP == 1 )
|
||||
/* The application writer has already defined the array used for the RTOS
|
||||
heap - probably so it can be placed in a special segment or address. */
|
||||
extern uint8_t ucHeap[configTOTAL_HEAP_SIZE];
|
||||
#else
|
||||
static uint8_t ucHeap[configTOTAL_HEAP_SIZE];
|
||||
#endif /* configAPPLICATION_ALLOCATED_HEAP */
|
||||
|
||||
/* Define the linked list structure. This is used to link free blocks in order
|
||||
of their memory address. */
|
||||
typedef struct A_BLOCK_LINK
|
||||
{
|
||||
struct A_BLOCK_LINK *pxNextFreeBlock; /*<< The next free block in the list. */
|
||||
size_t xBlockSize; /*<< The size of the free block. */
|
||||
} BlockLink_t;
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* Inserts a block of memory that is being freed into the correct position in
|
||||
* the list of free memory blocks. The block being freed will be merged with
|
||||
* the block in front it and/or the block behind it if the memory blocks are
|
||||
* adjacent to each other.
|
||||
*/
|
||||
static void prvInsertBlockIntoFreeList(BlockLink_t *pxBlockToInsert);
|
||||
|
||||
/*
|
||||
* Called automatically to setup the required heap structures the first time
|
||||
* pvPortMalloc() is called.
|
||||
*/
|
||||
static void prvHeapInit(void);
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* The size of the structure placed at the beginning of each allocated memory
|
||||
block must by correctly byte aligned. */
|
||||
static const size_t xHeapStructSize = (sizeof(BlockLink_t) + ((size_t)(portBYTE_ALIGNMENT - 1))) & ~((size_t)portBYTE_ALIGNMENT_MASK);
|
||||
|
||||
/* Create a couple of list links to mark the start and end of the list. */
|
||||
static BlockLink_t xStart, *pxEnd = NULL;
|
||||
|
||||
/* Keeps track of the number of free bytes remaining, but says nothing about
|
||||
fragmentation. */
|
||||
static size_t xFreeBytesRemaining = 0U;
|
||||
static size_t xMinimumEverFreeBytesRemaining = 0U;
|
||||
|
||||
/* Gets set to the top bit of an size_t type. When this bit in the xBlockSize
|
||||
member of an BlockLink_t structure is set then the block belongs to the
|
||||
application. When the bit is free the block is still part of the free heap
|
||||
space. */
|
||||
static size_t xBlockAllocatedBit = 0;
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void *pvPortMalloc(size_t xWantedSize)
|
||||
{
|
||||
BlockLink_t *pxBlock, *pxPreviousBlock, *pxNewBlockLink;
|
||||
void *pvReturn = NULL;
|
||||
|
||||
taskENTER_CRITICAL();
|
||||
{
|
||||
/* If this is the first call to malloc then the heap will require
|
||||
initialisation to setup the list of free blocks. */
|
||||
if (pxEnd == NULL)
|
||||
{
|
||||
prvHeapInit();
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
|
||||
/* Check the requested block size is not so large that the top bit is
|
||||
set. The top bit of the block size member of the BlockLink_t structure
|
||||
is used to determine who owns the block - the application or the
|
||||
kernel, so it must be free. */
|
||||
if ((xWantedSize & xBlockAllocatedBit) == 0)
|
||||
{
|
||||
/* The wanted size is increased so it can contain a BlockLink_t
|
||||
structure in addition to the requested amount of bytes. */
|
||||
if (xWantedSize > 0)
|
||||
{
|
||||
xWantedSize += xHeapStructSize;
|
||||
|
||||
/* Ensure that blocks are always aligned to the required number
|
||||
of bytes. */
|
||||
if ((xWantedSize & portBYTE_ALIGNMENT_MASK) != 0x00)
|
||||
{
|
||||
/* Byte alignment required. */
|
||||
xWantedSize += (portBYTE_ALIGNMENT - (xWantedSize & portBYTE_ALIGNMENT_MASK));
|
||||
configASSERT((xWantedSize & portBYTE_ALIGNMENT_MASK) == 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
|
||||
if ((xWantedSize > 0) && (xWantedSize <= xFreeBytesRemaining))
|
||||
{
|
||||
/* Traverse the list from the start (lowest address) block until
|
||||
one of adequate size is found. */
|
||||
pxPreviousBlock = &xStart;
|
||||
pxBlock = xStart.pxNextFreeBlock;
|
||||
while ((pxBlock->xBlockSize < xWantedSize) && (pxBlock->pxNextFreeBlock != NULL))
|
||||
{
|
||||
pxPreviousBlock = pxBlock;
|
||||
pxBlock = pxBlock->pxNextFreeBlock;
|
||||
}
|
||||
|
||||
/* If the end marker was reached then a block of adequate size
|
||||
was not found. */
|
||||
if (pxBlock != pxEnd)
|
||||
{
|
||||
/* Return the memory space pointed to - jumping over the
|
||||
BlockLink_t structure at its start. */
|
||||
pvReturn = (void *)(((uint8_t *)pxPreviousBlock->pxNextFreeBlock) + xHeapStructSize);
|
||||
|
||||
/* This block is being returned for use so must be taken out
|
||||
of the list of free blocks. */
|
||||
pxPreviousBlock->pxNextFreeBlock = pxBlock->pxNextFreeBlock;
|
||||
|
||||
/* If the block is larger than required it can be split into
|
||||
two. */
|
||||
if ((pxBlock->xBlockSize - xWantedSize) > heapMINIMUM_BLOCK_SIZE)
|
||||
{
|
||||
/* This block is to be split into two. Create a new
|
||||
block following the number of bytes requested. The void
|
||||
cast is used to prevent byte alignment warnings from the
|
||||
compiler. */
|
||||
pxNewBlockLink = (void *)(((uint8_t *)pxBlock) + xWantedSize);
|
||||
configASSERT((((size_t)pxNewBlockLink) & portBYTE_ALIGNMENT_MASK) == 0);
|
||||
|
||||
/* Calculate the sizes of two blocks split from the
|
||||
single block. */
|
||||
pxNewBlockLink->xBlockSize = pxBlock->xBlockSize - xWantedSize;
|
||||
pxBlock->xBlockSize = xWantedSize;
|
||||
|
||||
/* Insert the new block into the list of free blocks. */
|
||||
prvInsertBlockIntoFreeList(pxNewBlockLink);
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
|
||||
xFreeBytesRemaining -= pxBlock->xBlockSize;
|
||||
|
||||
if (xFreeBytesRemaining < xMinimumEverFreeBytesRemaining)
|
||||
{
|
||||
xMinimumEverFreeBytesRemaining = xFreeBytesRemaining;
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
|
||||
/* The block is being returned - it is allocated and owned
|
||||
by the application and has no "next" block. */
|
||||
pxBlock->xBlockSize |= xBlockAllocatedBit;
|
||||
pxBlock->pxNextFreeBlock = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
|
||||
traceMALLOC(pvReturn, xWantedSize);
|
||||
}
|
||||
(void)taskEXIT_CRITICAL();
|
||||
|
||||
#if( configUSE_MALLOC_FAILED_HOOK == 1 )
|
||||
{
|
||||
if (pvReturn == NULL)
|
||||
{
|
||||
extern void vApplicationMallocFailedHook(void);
|
||||
vApplicationMallocFailedHook();
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
configASSERT((((size_t)pvReturn) & (size_t)portBYTE_ALIGNMENT_MASK) == 0);
|
||||
return pvReturn;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortFree(void *pv)
|
||||
{
|
||||
uint8_t *puc = (uint8_t *)pv;
|
||||
BlockLink_t *pxLink;
|
||||
|
||||
if (pv != NULL)
|
||||
{
|
||||
/* The memory being freed will have an BlockLink_t structure immediately
|
||||
before it. */
|
||||
puc -= xHeapStructSize;
|
||||
|
||||
/* This casting is to keep the compiler from issuing warnings. */
|
||||
pxLink = (void *)puc;
|
||||
|
||||
/* Check the block is actually allocated. */
|
||||
configASSERT((pxLink->xBlockSize & xBlockAllocatedBit) != 0);
|
||||
configASSERT(pxLink->pxNextFreeBlock == NULL);
|
||||
|
||||
if ((pxLink->xBlockSize & xBlockAllocatedBit) != 0)
|
||||
{
|
||||
if (pxLink->pxNextFreeBlock == NULL)
|
||||
{
|
||||
/* The block is being returned to the heap - it is no longer
|
||||
allocated. */
|
||||
pxLink->xBlockSize &= ~xBlockAllocatedBit;
|
||||
|
||||
taskENTER_CRITICAL();
|
||||
{
|
||||
/* Add this block to the list of free blocks. */
|
||||
xFreeBytesRemaining += pxLink->xBlockSize;
|
||||
traceFREE(pv, pxLink->xBlockSize);
|
||||
prvInsertBlockIntoFreeList(((BlockLink_t *)pxLink));
|
||||
}
|
||||
(void)taskEXIT_CRITICAL();
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
size_t xPortGetFreeHeapSize(void)
|
||||
{
|
||||
return xFreeBytesRemaining;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
size_t xPortGetMinimumEverFreeHeapSize(void)
|
||||
{
|
||||
return xMinimumEverFreeBytesRemaining;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortInitialiseBlocks(void)
|
||||
{
|
||||
/* This just exists to keep the linker quiet. */
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static void prvHeapInit(void)
|
||||
{
|
||||
BlockLink_t *pxFirstFreeBlock;
|
||||
uint8_t *pucAlignedHeap;
|
||||
size_t uxAddress;
|
||||
size_t xTotalHeapSize = configTOTAL_HEAP_SIZE;
|
||||
|
||||
/* Ensure the heap starts on a correctly aligned boundary. */
|
||||
uxAddress = (size_t)ucHeap;
|
||||
|
||||
if ((uxAddress & portBYTE_ALIGNMENT_MASK) != 0)
|
||||
{
|
||||
uxAddress += (portBYTE_ALIGNMENT - 1);
|
||||
uxAddress &= ~((size_t)portBYTE_ALIGNMENT_MASK);
|
||||
xTotalHeapSize -= uxAddress - (size_t)ucHeap;
|
||||
}
|
||||
|
||||
pucAlignedHeap = (uint8_t *)uxAddress;
|
||||
|
||||
/* xStart is used to hold a pointer to the first item in the list of free
|
||||
blocks. The void cast is used to prevent compiler warnings. */
|
||||
xStart.pxNextFreeBlock = (void *)pucAlignedHeap;
|
||||
xStart.xBlockSize = (size_t)0;
|
||||
|
||||
/* pxEnd is used to mark the end of the list of free blocks and is inserted
|
||||
at the end of the heap space. */
|
||||
uxAddress = ((size_t)pucAlignedHeap) + xTotalHeapSize;
|
||||
uxAddress -= xHeapStructSize;
|
||||
uxAddress &= ~((size_t)portBYTE_ALIGNMENT_MASK);
|
||||
pxEnd = (void *)uxAddress;
|
||||
pxEnd->xBlockSize = 0;
|
||||
pxEnd->pxNextFreeBlock = NULL;
|
||||
|
||||
/* To start with there is a single free block that is sized to take up the
|
||||
entire heap space, minus the space taken by pxEnd. */
|
||||
pxFirstFreeBlock = (void *)pucAlignedHeap;
|
||||
pxFirstFreeBlock->xBlockSize = uxAddress - (size_t)pxFirstFreeBlock;
|
||||
pxFirstFreeBlock->pxNextFreeBlock = pxEnd;
|
||||
|
||||
/* Only one block exists - and it covers the entire usable heap space. */
|
||||
xMinimumEverFreeBytesRemaining = pxFirstFreeBlock->xBlockSize;
|
||||
xFreeBytesRemaining = pxFirstFreeBlock->xBlockSize;
|
||||
|
||||
/* Work out the position of the top bit in a size_t variable. */
|
||||
xBlockAllocatedBit = ((size_t)1) << ((sizeof(size_t) * heapBITS_PER_BYTE) - 1);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static void prvInsertBlockIntoFreeList(BlockLink_t *pxBlockToInsert)
|
||||
{
|
||||
BlockLink_t *pxIterator;
|
||||
uint8_t *puc;
|
||||
|
||||
/* Iterate through the list until a block is found that has a higher address
|
||||
than the block being inserted. */
|
||||
for (pxIterator = &xStart; pxIterator->pxNextFreeBlock < pxBlockToInsert; pxIterator = pxIterator->pxNextFreeBlock)
|
||||
{
|
||||
/* Nothing to do here, just iterate to the right position. */
|
||||
}
|
||||
|
||||
/* Do the block being inserted, and the block it is being inserted after
|
||||
make a contiguous block of memory? */
|
||||
puc = (uint8_t *)pxIterator;
|
||||
if ((puc + pxIterator->xBlockSize) == (uint8_t *)pxBlockToInsert)
|
||||
{
|
||||
pxIterator->xBlockSize += pxBlockToInsert->xBlockSize;
|
||||
pxBlockToInsert = pxIterator;
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
|
||||
/* Do the block being inserted, and the block it is being inserted before
|
||||
make a contiguous block of memory? */
|
||||
puc = (uint8_t *)pxBlockToInsert;
|
||||
if ((puc + pxBlockToInsert->xBlockSize) == (uint8_t *)pxIterator->pxNextFreeBlock)
|
||||
{
|
||||
if (pxIterator->pxNextFreeBlock != pxEnd)
|
||||
{
|
||||
/* Form one big block from the two blocks. */
|
||||
pxBlockToInsert->xBlockSize += pxIterator->pxNextFreeBlock->xBlockSize;
|
||||
pxBlockToInsert->pxNextFreeBlock = pxIterator->pxNextFreeBlock->pxNextFreeBlock;
|
||||
}
|
||||
else
|
||||
{
|
||||
pxBlockToInsert->pxNextFreeBlock = pxEnd;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
pxBlockToInsert->pxNextFreeBlock = pxIterator->pxNextFreeBlock;
|
||||
}
|
||||
|
||||
/* If the block being inserted plugged a gab, so was merged with the block
|
||||
before and the block after, then it's pxNextFreeBlock pointer will have
|
||||
already been set, and should not be set here as that would make it point
|
||||
to itself. */
|
||||
if (pxIterator != pxBlockToInsert)
|
||||
{
|
||||
pxIterator->pxNextFreeBlock = pxBlockToInsert;
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user