Update BSP and SDK for HiFive board (#645)

* Update BSP and SDK for HiFive board

This commit also adds demo start and success/failure output messages.
This commit is contained in:
Gaurav-Aggarwal-AWS
2021-07-15 18:40:22 -07:00
committed by GitHub
parent b550e6090d
commit 2fedeff332
263 changed files with 36551 additions and 6623 deletions
@@ -1,176 +1,93 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<?fileVersion 4.0.0?><cproject storage_type_id="org.eclipse.cdt.core.XmlProjectDescriptionStorage">
<storageModule moduleId="org.eclipse.cdt.core.settings">
<cconfiguration id="cdt.managedbuild.config.gnu.cross.exe.debug.206163480">
<storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="cdt.managedbuild.config.gnu.cross.exe.debug.206163480" moduleId="org.eclipse.cdt.core.settings" name="Debug">
<externalSettings/>
<extensions>
<extension id="org.eclipse.cdt.core.ELF" point="org.eclipse.cdt.core.BinaryParser"/>
<extension id="org.eclipse.cdt.core.GASErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
<extension id="org.eclipse.cdt.core.GmakeErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
<extension id="org.eclipse.cdt.core.GLDErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
<extension id="org.eclipse.cdt.core.CWDLocator" point="org.eclipse.cdt.core.ErrorParser"/>
<extension id="org.eclipse.cdt.core.GCCErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
</extensions>
</storageModule>
<storageModule moduleId="cdtBuildSystem" version="4.0.0">
<configuration artifactName="${ProjName}" buildArtefactType="org.eclipse.cdt.build.core.buildArtefactType.exe" buildProperties="org.eclipse.cdt.build.core.buildArtefactType=org.eclipse.cdt.build.core.buildArtefactType.exe,org.eclipse.cdt.build.core.buildType=org.eclipse.cdt.build.core.buildType.debug" cleanCommand="rm -rf" description="" id="cdt.managedbuild.config.gnu.cross.exe.debug.206163480" name="Debug" parent="cdt.managedbuild.config.gnu.cross.exe.debug">
<folderInfo id="cdt.managedbuild.config.gnu.cross.exe.debug.206163480." name="/" resourcePath="">
<toolChain id="cdt.managedbuild.toolchain.gnu.cross.exe.debug.1023181676" name="Cross GCC" superClass="cdt.managedbuild.toolchain.gnu.cross.exe.debug">
<option id="cdt.managedbuild.option.gnu.cross.path.2116215758" name="Path" superClass="cdt.managedbuild.option.gnu.cross.path" useByScannerDiscovery="false" value="${eclipse_home}/SiFive/riscv64-unknown-elf-gcc-8.3.0-2019.08.0/bin" valueType="string"/>
<targetPlatform archList="all" binaryParser="org.eclipse.cdt.core.ELF" id="cdt.managedbuild.targetPlatform.gnu.cross.1119183919" isAbstract="false" osList="all" superClass="cdt.managedbuild.targetPlatform.gnu.cross"/>
<builder buildPath="${workspace_loc:/RTOSDemo}/Debug" id="cdt.managedbuild.builder.gnu.cross.1388532167" keepEnvironmentInBuildfile="false" managedBuildOn="true" name="Gnu Make Builder" parallelBuildOn="true" parallelizationNumber="optimal" superClass="cdt.managedbuild.builder.gnu.cross"/>
<tool command="riscv64-unknown-elf-gcc" id="cdt.managedbuild.tool.gnu.cross.c.compiler.1469975065" name="Cross GCC Compiler" superClass="cdt.managedbuild.tool.gnu.cross.c.compiler">
<option defaultValue="gnu.c.optimization.level.none" id="gnu.c.compiler.option.optimization.level.440219377" name="Optimization Level" superClass="gnu.c.compiler.option.optimization.level" useByScannerDiscovery="false" valueType="enumerated"/>
<option id="gnu.c.compiler.option.debugging.level.1721555429" name="Debug Level" superClass="gnu.c.compiler.option.debugging.level" useByScannerDiscovery="false" value="gnu.c.debugging.level.max" valueType="enumerated"/>
<option id="gnu.c.compiler.option.dialect.std.1648189865" name="Language standard" superClass="gnu.c.compiler.option.dialect.std" useByScannerDiscovery="true" value="gnu.c.compiler.dialect.default" valueType="enumerated"/>
<option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="gnu.c.compiler.option.include.paths.1720192082" name="Include paths (-I)" superClass="gnu.c.compiler.option.include.paths" useByScannerDiscovery="false" valueType="includePath">
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/FreeRTOS_Source/include}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/full_demo/Common_Demo_Tasks/include}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/FreeRTOS_Source/portable/GCC/RISC-V}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/FreeRTOS_Source/include}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/freedom-metal}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/bsp/install/include}&quot;"/>
</option>
<option id="gnu.c.compiler.option.misc.other.257964774" name="Other flags" superClass="gnu.c.compiler.option.misc.other" useByScannerDiscovery="false" value="-c -fmessage-length=0 -march=rv32imac -mabi=ilp32 -mcmodel=medlow -ffunction-sections -fdata-sections --specs=nano.specs -Wno-unused-parameter" valueType="string"/>
<option id="gnu.c.compiler.option.warnings.extrawarn.1802410957" name="Extra warnings (-Wextra)" superClass="gnu.c.compiler.option.warnings.extrawarn" useByScannerDiscovery="false" value="true" valueType="boolean"/>
<inputType id="cdt.managedbuild.tool.gnu.c.compiler.input.1079251302" superClass="cdt.managedbuild.tool.gnu.c.compiler.input"/>
</tool>
<tool id="cdt.managedbuild.tool.gnu.cross.cpp.compiler.420742449" name="Cross G++ Compiler" superClass="cdt.managedbuild.tool.gnu.cross.cpp.compiler">
<option id="gnu.cpp.compiler.option.optimization.level.1056760450" name="Optimization Level" superClass="gnu.cpp.compiler.option.optimization.level" useByScannerDiscovery="false" value="gnu.cpp.compiler.optimization.level.none" valueType="enumerated"/>
<option id="gnu.cpp.compiler.option.debugging.level.52506316" name="Debug Level" superClass="gnu.cpp.compiler.option.debugging.level" useByScannerDiscovery="false" value="gnu.cpp.compiler.debugging.level.max" valueType="enumerated"/>
</tool>
<tool command="riscv64-unknown-elf-gcc" id="cdt.managedbuild.tool.gnu.cross.c.linker.558060359" name="Cross GCC Linker" superClass="cdt.managedbuild.tool.gnu.cross.c.linker">
<option id="gnu.c.link.option.ldflags.46965227" name="Linker flags" superClass="gnu.c.link.option.ldflags" useByScannerDiscovery="false" value="-Xlinker --gc-sections -Wl,-Map,RTOSDemo.map -T../bsp/metal.default.lds -march=rv32imac -mabi=ilp32 -mcmodel=medlow -Wl,--start-group -lc -lgcc -Wl,--end-group --specs=nano.specs" valueType="string"/>
<option id="gnu.c.link.option.nostart.1038463237" name="Do not use standard start files (-nostartfiles)" superClass="gnu.c.link.option.nostart" useByScannerDiscovery="false" value="true" valueType="boolean"/>
<option id="gnu.c.link.option.nostdlibs.934043026" name="No startup or default libs (-nostdlib)" superClass="gnu.c.link.option.nostdlibs" useByScannerDiscovery="false" value="false" valueType="boolean"/>
<option id="gnu.c.link.option.nodeflibs.1095611620" name="Do not use default libraries (-nodefaultlibs)" superClass="gnu.c.link.option.nodeflibs" useByScannerDiscovery="false" value="false" valueType="boolean"/>
<inputType id="cdt.managedbuild.tool.gnu.c.linker.input.549526426" superClass="cdt.managedbuild.tool.gnu.c.linker.input">
<additionalInput kind="additionalinputdependency" paths="$(USER_OBJS)"/>
<additionalInput kind="additionalinput" paths="$(LIBS)"/>
</inputType>
</tool>
<tool id="cdt.managedbuild.tool.gnu.cross.cpp.linker.2105463183" name="Cross G++ Linker" superClass="cdt.managedbuild.tool.gnu.cross.cpp.linker"/>
<tool id="cdt.managedbuild.tool.gnu.cross.archiver.424513814" name="Cross GCC Archiver" superClass="cdt.managedbuild.tool.gnu.cross.archiver"/>
<tool command="riscv64-unknown-elf-gcc" id="cdt.managedbuild.tool.gnu.cross.assembler.825438707" name="Cross GCC Assembler" superClass="cdt.managedbuild.tool.gnu.cross.assembler">
<option id="gnu.both.asm.option.flags.1946908814" name="Assembler flags" superClass="gnu.both.asm.option.flags" useByScannerDiscovery="false" value="-march=rv32imac -mabi=ilp32 -mcmodel=medlow -c -DportasmHANDLE_INTERRUPT=handle_trap -g3" valueType="string"/>
<option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="gnu.both.asm.option.include.paths.1448234506" name="Include paths (-I)" superClass="gnu.both.asm.option.include.paths" useByScannerDiscovery="false" valueType="includePath">
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/FreeRTOS_Source/portable/GCC/RISC-V/chip_specific_extensions/RV32I_CLINT_no_extensions}&quot;"/>
</option>
<inputType id="cdt.managedbuild.tool.gnu.assembler.input.1723023894" superClass="cdt.managedbuild.tool.gnu.assembler.input"/>
</tool>
</toolChain>
</folderInfo>
<sourceEntries>
<entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name=""/>
</sourceEntries>
</configuration>
</storageModule>
<storageModule moduleId="org.eclipse.cdt.core.externalSettings"/>
</cconfiguration>
</storageModule>
<storageModule moduleId="cdtBuildSystem" version="4.0.0">
<project id="RTOSDemo.cdt.managedbuild.target.gnu.cross.exe.1669036252" name="Executable" projectType="cdt.managedbuild.target.gnu.cross.exe"/>
</storageModule>
<storageModule moduleId="scannerConfiguration">
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
<scannerConfigBuildInfo instanceId="cdt.managedbuild.config.gnu.cross.exe.debug.206163480;cdt.managedbuild.config.gnu.cross.exe.debug.206163480.;cdt.managedbuild.tool.gnu.cross.c.compiler.1469975065;cdt.managedbuild.tool.gnu.c.compiler.input.1079251302">
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
</scannerConfigBuildInfo>
</storageModule>
<storageModule moduleId="org.eclipse.cdt.core.LanguageSettingsProviders"/>
<storageModule moduleId="org.eclipse.cdt.make.core.buildtargets"/>
<storageModule moduleId="refreshScope" versionNumber="2">
<configuration configurationName="Debug">
<resource resourceType="PROJECT" workspacePath="/RTOSDemo"/>
</configuration>
</storageModule>
</cproject>
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<?fileVersion 4.0.0?><cproject storage_type_id="org.eclipse.cdt.core.XmlProjectDescriptionStorage">
<storageModule moduleId="org.eclipse.cdt.core.settings">
<cconfiguration id="cdt.managedbuild.config.gnu.cross.exe.debug.206163480">
<storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="cdt.managedbuild.config.gnu.cross.exe.debug.206163480" moduleId="org.eclipse.cdt.core.settings" name="Debug">
<externalSettings/>
<extensions>
<extension id="org.eclipse.cdt.core.ELF" point="org.eclipse.cdt.core.BinaryParser"/>
<extension id="org.eclipse.cdt.core.GASErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
<extension id="org.eclipse.cdt.core.GmakeErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
<extension id="org.eclipse.cdt.core.GLDErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
<extension id="org.eclipse.cdt.core.CWDLocator" point="org.eclipse.cdt.core.ErrorParser"/>
<extension id="org.eclipse.cdt.core.GCCErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
</extensions>
</storageModule>
<storageModule moduleId="cdtBuildSystem" version="4.0.0">
<configuration artifactName="${ProjName}" buildArtefactType="org.eclipse.cdt.build.core.buildArtefactType.exe" buildProperties="org.eclipse.cdt.build.core.buildArtefactType=org.eclipse.cdt.build.core.buildArtefactType.exe,org.eclipse.cdt.build.core.buildType=org.eclipse.cdt.build.core.buildType.debug" cleanCommand="rm -rf" description="" id="cdt.managedbuild.config.gnu.cross.exe.debug.206163480" name="Debug" parent="cdt.managedbuild.config.gnu.cross.exe.debug" postbuildStep="riscv64-unknown-elf-objcopy -O binary ${ProjName} ${ProjName}.bin">
<folderInfo id="cdt.managedbuild.config.gnu.cross.exe.debug.206163480." name="/" resourcePath="">
<toolChain id="cdt.managedbuild.toolchain.gnu.cross.exe.debug.1023181676" name="Cross GCC" superClass="cdt.managedbuild.toolchain.gnu.cross.exe.debug">
<option id="cdt.managedbuild.option.gnu.cross.path.2116215758" name="Path" superClass="cdt.managedbuild.option.gnu.cross.path" useByScannerDiscovery="false" value="${eclipse_home}/SiFive/riscv64-unknown-elf-toolchain-10.2.0-2020.12.8/bin" valueType="string"/>
<targetPlatform archList="all" binaryParser="org.eclipse.cdt.core.ELF" id="cdt.managedbuild.targetPlatform.gnu.cross.1119183919" isAbstract="false" osList="all" superClass="cdt.managedbuild.targetPlatform.gnu.cross"/>
<builder buildPath="${workspace_loc:/RTOSDemo}/Debug" id="cdt.managedbuild.builder.gnu.cross.1388532167" keepEnvironmentInBuildfile="false" managedBuildOn="true" name="Gnu Make Builder" parallelBuildOn="true" parallelizationNumber="optimal" superClass="cdt.managedbuild.builder.gnu.cross"/>
<tool command="riscv64-unknown-elf-gcc" id="cdt.managedbuild.tool.gnu.cross.c.compiler.1469975065" name="Cross GCC Compiler" superClass="cdt.managedbuild.tool.gnu.cross.c.compiler">
<option defaultValue="gnu.c.optimization.level.none" id="gnu.c.compiler.option.optimization.level.440219377" name="Optimization Level" superClass="gnu.c.compiler.option.optimization.level" useByScannerDiscovery="false" valueType="enumerated"/>
<option id="gnu.c.compiler.option.debugging.level.1721555429" name="Debug Level" superClass="gnu.c.compiler.option.debugging.level" useByScannerDiscovery="false" value="gnu.c.debugging.level.max" valueType="enumerated"/>
<option id="gnu.c.compiler.option.dialect.std.1648189865" name="Language standard" superClass="gnu.c.compiler.option.dialect.std" useByScannerDiscovery="true" value="gnu.c.compiler.dialect.default" valueType="enumerated"/>
<option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="gnu.c.compiler.option.include.paths.1720192082" name="Include paths (-I)" superClass="gnu.c.compiler.option.include.paths" useByScannerDiscovery="false" valueType="includePath">
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/FreeRTOS_Source/include}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/full_demo/Common_Demo_Tasks/include}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/FreeRTOS_Source/portable/GCC/RISC-V}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/FreeRTOS_Source/include}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/freedom-metal}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/bsp/install/include}&quot;"/>
</option>
<option id="gnu.c.compiler.option.misc.other.257964774" name="Other flags" superClass="gnu.c.compiler.option.misc.other" useByScannerDiscovery="false" value="-c -fmessage-length=0 -march=rv32imac -mabi=ilp32 -mcmodel=medlow -ffunction-sections -fdata-sections --specs=nano.specs -Wno-unused-parameter" valueType="string"/>
<option id="gnu.c.compiler.option.warnings.extrawarn.1802410957" name="Extra warnings (-Wextra)" superClass="gnu.c.compiler.option.warnings.extrawarn" useByScannerDiscovery="false" value="true" valueType="boolean"/>
<inputType id="cdt.managedbuild.tool.gnu.c.compiler.input.1079251302" superClass="cdt.managedbuild.tool.gnu.c.compiler.input"/>
</tool>
<tool id="cdt.managedbuild.tool.gnu.cross.cpp.compiler.420742449" name="Cross G++ Compiler" superClass="cdt.managedbuild.tool.gnu.cross.cpp.compiler">
<option id="gnu.cpp.compiler.option.optimization.level.1056760450" name="Optimization Level" superClass="gnu.cpp.compiler.option.optimization.level" useByScannerDiscovery="false" value="gnu.cpp.compiler.optimization.level.none" valueType="enumerated"/>
<option id="gnu.cpp.compiler.option.debugging.level.52506316" name="Debug Level" superClass="gnu.cpp.compiler.option.debugging.level" useByScannerDiscovery="false" value="gnu.cpp.compiler.debugging.level.max" valueType="enumerated"/>
</tool>
<tool command="riscv64-unknown-elf-gcc" id="cdt.managedbuild.tool.gnu.cross.c.linker.558060359" name="Cross GCC Linker" superClass="cdt.managedbuild.tool.gnu.cross.c.linker">
<option id="gnu.c.link.option.ldflags.46965227" name="Linker flags" superClass="gnu.c.link.option.ldflags" useByScannerDiscovery="false" value="-Xlinker --gc-sections -Wl,-Map,RTOSDemo.map -T../bsp/metal.default.lds -march=rv32imac -mabi=ilp32 -mcmodel=medlow -Wl,--start-group -lc -lgcc -Wl,--end-group --specs=nano.specs" valueType="string"/>
<option id="gnu.c.link.option.nostart.1038463237" name="Do not use standard start files (-nostartfiles)" superClass="gnu.c.link.option.nostart" useByScannerDiscovery="false" value="true" valueType="boolean"/>
<option id="gnu.c.link.option.nostdlibs.934043026" name="No startup or default libs (-nostdlib)" superClass="gnu.c.link.option.nostdlibs" useByScannerDiscovery="false" value="false" valueType="boolean"/>
<option id="gnu.c.link.option.nodeflibs.1095611620" name="Do not use default libraries (-nodefaultlibs)" superClass="gnu.c.link.option.nodeflibs" useByScannerDiscovery="false" value="false" valueType="boolean"/>
<option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="gnu.c.link.option.other.875927818" name="Other options (-Xlinker [option])" superClass="gnu.c.link.option.other" useByScannerDiscovery="false" valueType="stringList">
<listOptionValue builtIn="false" value="--defsym=__heap_max=1"/>
</option>
<inputType id="cdt.managedbuild.tool.gnu.c.linker.input.549526426" superClass="cdt.managedbuild.tool.gnu.c.linker.input">
<additionalInput kind="additionalinputdependency" paths="$(USER_OBJS)"/>
<additionalInput kind="additionalinput" paths="$(LIBS)"/>
</inputType>
</tool>
<tool id="cdt.managedbuild.tool.gnu.cross.cpp.linker.2105463183" name="Cross G++ Linker" superClass="cdt.managedbuild.tool.gnu.cross.cpp.linker"/>
<tool id="cdt.managedbuild.tool.gnu.cross.archiver.424513814" name="Cross GCC Archiver" superClass="cdt.managedbuild.tool.gnu.cross.archiver"/>
<tool command="riscv64-unknown-elf-gcc" id="cdt.managedbuild.tool.gnu.cross.assembler.825438707" name="Cross GCC Assembler" superClass="cdt.managedbuild.tool.gnu.cross.assembler">
<option id="gnu.both.asm.option.flags.1946908814" name="Assembler flags" superClass="gnu.both.asm.option.flags" useByScannerDiscovery="false" value="-march=rv32imac -mabi=ilp32 -mcmodel=medlow -c -DportasmHANDLE_INTERRUPT=handle_trap -g3" valueType="string"/>
<option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="gnu.both.asm.option.include.paths.1448234506" name="Include paths (-I)" superClass="gnu.both.asm.option.include.paths" useByScannerDiscovery="false" valueType="includePath">
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/FreeRTOS_Source/portable/GCC/RISC-V/chip_specific_extensions/RV32I_CLINT_no_extensions}&quot;"/>
</option>
<inputType id="cdt.managedbuild.tool.gnu.assembler.input.1723023894" superClass="cdt.managedbuild.tool.gnu.assembler.input"/>
</tool>
</toolChain>
</folderInfo>
<sourceEntries>
<entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name=""/>
</sourceEntries>
</configuration>
</storageModule>
<storageModule moduleId="org.eclipse.cdt.core.externalSettings"/>
</cconfiguration>
</storageModule>
<storageModule moduleId="cdtBuildSystem" version="4.0.0">
<project id="RTOSDemo.cdt.managedbuild.target.gnu.cross.exe.1669036252" name="Executable" projectType="cdt.managedbuild.target.gnu.cross.exe"/>
</storageModule>
<storageModule moduleId="scannerConfiguration">
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
<scannerConfigBuildInfo instanceId="cdt.managedbuild.config.gnu.cross.exe.debug.206163480;cdt.managedbuild.config.gnu.cross.exe.debug.206163480.;cdt.managedbuild.tool.gnu.cross.c.compiler.1469975065;cdt.managedbuild.tool.gnu.c.compiler.input.1079251302">
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
</scannerConfigBuildInfo>
</storageModule>
<storageModule moduleId="org.eclipse.cdt.core.LanguageSettingsProviders"/>
<storageModule moduleId="org.eclipse.cdt.make.core.buildtargets"/>
<storageModule moduleId="refreshScope" versionNumber="2">
<configuration configurationName="Debug">
<resource resourceType="PROJECT" workspacePath="/RTOSDemo"/>
</configuration>
</storageModule>
<storageModule moduleId="org.eclipse.cdt.internal.ui.text.commentOwnerProjectMappings"/>
</cproject>
File diff suppressed because it is too large Load Diff
@@ -1,26 +1,14 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<project>
<configuration id="cdt.managedbuild.config.gnu.cross.exe.debug.206163480" name="Debug">
<extension point="org.eclipse.cdt.core.LanguageSettingsProvider">
<provider copy-of="extension" id="org.eclipse.cdt.ui.UserLanguageSettingsProvider"/>
<provider-reference id="org.eclipse.cdt.core.ReferencedProjectsLanguageSettingsProvider" ref="shared-provider"/>
<provider-reference id="org.eclipse.cdt.managedbuilder.core.MBSLanguageSettingsProvider" ref="shared-provider"/>
<provider class="org.eclipse.cdt.internal.build.crossgcc.CrossGCCBuiltinSpecsDetector" console="false" env-hash="-1852838222473283" id="org.eclipse.cdt.build.crossgcc.CrossGCCBuiltinSpecsDetector" keep-relative-paths="false" name="CDT Cross GCC Built-in Compiler Settings" parameter="${COMMAND} ${FLAGS} -E -P -v -dD &quot;${INPUTS}&quot;" prefer-non-shared="true">
<language-scope id="org.eclipse.cdt.core.gcc"/>
<language-scope id="org.eclipse.cdt.core.g++"/>
</provider>
</extension>
</configuration>
</project>
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<project>
<configuration id="cdt.managedbuild.config.gnu.cross.exe.debug.206163480" name="Debug">
<extension point="org.eclipse.cdt.core.LanguageSettingsProvider">
<provider copy-of="extension" id="org.eclipse.cdt.ui.UserLanguageSettingsProvider"/>
<provider-reference id="org.eclipse.cdt.core.ReferencedProjectsLanguageSettingsProvider" ref="shared-provider"/>
<provider-reference id="org.eclipse.cdt.managedbuilder.core.MBSLanguageSettingsProvider" ref="shared-provider"/>
<provider class="org.eclipse.cdt.internal.build.crossgcc.CrossGCCBuiltinSpecsDetector" console="false" env-hash="644150116465149599" id="org.eclipse.cdt.build.crossgcc.CrossGCCBuiltinSpecsDetector" keep-relative-paths="false" name="CDT Cross GCC Built-in Compiler Settings" parameter="${COMMAND} ${FLAGS} -E -P -v -dD &quot;${INPUTS}&quot;" prefer-non-shared="true">
<language-scope id="org.eclipse.cdt.core.gcc"/>
<language-scope id="org.eclipse.cdt.core.g++"/>
</provider>
</extension>
</configuration>
</project>
@@ -1,102 +1,105 @@
/*
* FreeRTOS V202104.00
* Copyright (C) 2020 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.
*----------------------------------------------------------*/
#define CLINT_CTRL_ADDR ( 0x02000000UL )
#define configMTIME_BASE_ADDRESS ( CLINT_CTRL_ADDR + 0xBFF8UL )
#define configMTIMECMP_BASE_ADDRESS ( CLINT_CTRL_ADDR + 0x4000UL )
#define configUSE_PREEMPTION 1
#define configUSE_IDLE_HOOK 0
#define configUSE_TICK_HOOK 1
#define configCPU_CLOCK_HZ ( 32768 )
#define configTICK_RATE_HZ ( ( TickType_t ) 1000 )
#define configMAX_PRIORITIES ( 7 )
#define configMINIMAL_STACK_SIZE ( ( unsigned short ) 120 ) /* Only needs to be this high as some demo tasks also use this constant. In production only the idle task would use this. */
#define configTOTAL_HEAP_SIZE ( ( size_t ) 10900 )
#define configMAX_TASK_NAME_LEN ( 16 )
#define configUSE_TRACE_FACILITY 0
#define configUSE_16_BIT_TICKS 0
#define configIDLE_SHOULD_YIELD 0
#define configUSE_MUTEXES 1
#define configQUEUE_REGISTRY_SIZE 8
#define configCHECK_FOR_STACK_OVERFLOW 2
#define configUSE_RECURSIVE_MUTEXES 1
#define configUSE_MALLOC_FAILED_HOOK 1
#define configUSE_APPLICATION_TASK_TAG 0
#define configUSE_COUNTING_SEMAPHORES 1
#define configGENERATE_RUN_TIME_STATS 0
#define configUSE_PORT_OPTIMISED_TASK_SELECTION 1
/* Co-routine definitions. */
#define configUSE_CO_ROUTINES 0
#define configMAX_CO_ROUTINE_PRIORITIES ( 2 )
/* Software timer definitions. */
#define configUSE_TIMERS 1
#define configTIMER_TASK_PRIORITY ( configMAX_PRIORITIES - 1 )
#define configTIMER_QUEUE_LENGTH 8
#define configTIMER_TASK_STACK_DEPTH ( 160 )
/* Task priorities. Allow these to be overridden. */
#ifndef uartPRIMARY_PRIORITY
#define uartPRIMARY_PRIORITY ( configMAX_PRIORITIES - 3 )
#endif
/* 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_xTimerPendFunctionCall 1
#define INCLUDE_xTaskAbortDelay 1
#define INCLUDE_xTaskGetHandle 1
#define INCLUDE_xSemaphoreGetMutexHolder 1
/* Normal assert() semantics without relying on the provision of an assert.h
header file. */
void vAssertCalled( void );
#define configASSERT( x ) if( ( x ) == 0 ) vAssertCalled()
#endif /* FREERTOS_CONFIG_H */
/*
* FreeRTOS V202104.00
* Copyright (C) 2020 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.
*----------------------------------------------------------*/
#define CLINT_CTRL_ADDR ( 0x02000000UL )
#define configMTIME_BASE_ADDRESS ( CLINT_CTRL_ADDR + 0xBFF8UL )
#define configMTIMECMP_BASE_ADDRESS ( CLINT_CTRL_ADDR + 0x4000UL )
#define configUSE_PREEMPTION 1
#define configUSE_IDLE_HOOK 0
#define configUSE_TICK_HOOK 1
#define configCPU_CLOCK_HZ ( 32768 )
#define configTICK_RATE_HZ ( ( TickType_t ) 1000 )
#define configMAX_PRIORITIES ( 7 )
#define configMINIMAL_STACK_SIZE ( ( unsigned short ) 120 ) /* Only needs to be this high as some demo tasks also use this constant. In production only the idle task would use this. */
#define configTOTAL_HEAP_SIZE ( ( size_t ) 10900 )
#define configMAX_TASK_NAME_LEN ( 16 )
#define configUSE_TRACE_FACILITY 0
#define configUSE_16_BIT_TICKS 0
#define configIDLE_SHOULD_YIELD 0
#define configUSE_MUTEXES 1
#define configQUEUE_REGISTRY_SIZE 8
#define configCHECK_FOR_STACK_OVERFLOW 2
#define configUSE_RECURSIVE_MUTEXES 1
#define configUSE_MALLOC_FAILED_HOOK 1
#define configUSE_APPLICATION_TASK_TAG 0
#define configUSE_COUNTING_SEMAPHORES 1
#define configGENERATE_RUN_TIME_STATS 0
#define configUSE_PORT_OPTIMISED_TASK_SELECTION 1
/* Co-routine definitions. */
#define configUSE_CO_ROUTINES 0
#define configMAX_CO_ROUTINE_PRIORITIES ( 2 )
/* Software timer definitions. */
#define configUSE_TIMERS 1
#define configTIMER_TASK_PRIORITY ( configMAX_PRIORITIES - 1 )
#define configTIMER_QUEUE_LENGTH 8
#define configTIMER_TASK_STACK_DEPTH ( 160 )
/* Task priorities. Allow these to be overridden. */
#ifndef uartPRIMARY_PRIORITY
#define uartPRIMARY_PRIORITY ( configMAX_PRIORITIES - 3 )
#endif
/* 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_xTimerPendFunctionCall 1
#define INCLUDE_xTaskAbortDelay 1
#define INCLUDE_xTaskGetHandle 1
#define INCLUDE_xSemaphoreGetMutexHolder 1
/* Normal assert() semantics without relying on the provision of an assert.h
header file. */
void vAssertCalled( void );
#define configASSERT( x ) if( ( x ) == 0 ) vAssertCalled()
/* Map to the platform write function. */
#define configPRINT_STRING( pcString ) write( STDOUT_FILENO, pcString, strlen( pcString ) )
#endif /* FREERTOS_CONFIG_H */
@@ -1,5 +1,5 @@
[InternetShortcut]
URL=https://www.freertos.org/RTOS-RISC-V-FreedomStudio-IAR-HiFive-RevB.html
IDList=
[{000214A0-0000-0000-C000-000000000046}]
Prop3=19,2
[InternetShortcut]
URL=https://www.freertos.org/RTOS-RISC-V-FreedomStudio-IAR-HiFive-RevB.html
IDList=
[{000214A0-0000-0000-C000-000000000046}]
Prop3=19,2
@@ -1,197 +1,197 @@
/*
* FreeRTOS V202104.00
* Copyright (C) 2020 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!
*/
/******************************************************************************
* NOTE 1: This project provides two demo applications. A simple blinky
* style project, and a more comprehensive test and demo application. The
* mainCREATE_SIMPLE_BLINKY_DEMO_ONLY setting in main.c is used to select
* between the two. See the notes on using mainCREATE_SIMPLE_BLINKY_DEMO_ONLY
* in main.c. This file implements the simply blinky style version.
*
* NOTE 2: This file only contains the source code that is specific to the
* blinky demo. Generic functions, such FreeRTOS hook functions, and functions
* required to configure the hardware are defined in main.c.
******************************************************************************
*
* main_blinky() creates one queue, and two tasks. It then starts the
* scheduler.
*
* The Queue Send Task:
* The queue send task is implemented by the prvQueueSendTask() function in
* this file. prvQueueSendTask() sits in a loop that causes it to repeatedly
* block for 1000 milliseconds, before sending the value 100 to the queue that
* was created within main_blinky(). Once the value is sent, the task loops
* back around to block for another 1000 milliseconds...and so on.
*
* The Queue Receive Task:
* The queue receive task is implemented by the prvQueueReceiveTask() function
* in this file. prvQueueReceiveTask() sits in a loop where it repeatedly
* blocks on attempts to read data from the queue that was created within
* main_blinky(). When data is received, the task checks the value of the
* data, and if the value equals the expected 100, toggles an LED. The 'block
* time' parameter passed to the queue receive function specifies that the task
* should be held in the Blocked state indefinitely to wait for data to be
* available on the queue. The queue receive task will only leave the Blocked
* state when the queue send task writes to the queue. As the queue send task
* writes to the queue every 1000 milliseconds, the queue receive task leaves
* the Blocked state every 1000 milliseconds, and therefore toggles the LED
* every 200 milliseconds.
*/
/* Standard includes. */
#include <stdio.h>
#include <string.h>
#include <unistd.h>
/* Kernel includes. */
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
/* Priorities used by the tasks. */
#define mainQUEUE_RECEIVE_TASK_PRIORITY ( tskIDLE_PRIORITY + 2 )
#define mainQUEUE_SEND_TASK_PRIORITY ( tskIDLE_PRIORITY + 1 )
/* The rate at which data is sent to the queue. The 200ms value is converted
to ticks using the pdMS_TO_TICKS() macro. */
#define mainQUEUE_SEND_FREQUENCY_MS pdMS_TO_TICKS( 1000 )
/* The maximum number items the queue can hold. The priority of the receiving
task is above the priority of the sending task, so the receiving task will
preempt the sending task and remove the queue items each time the sending task
writes to the queue. Therefore the queue will never have more than one item in
it at any time, and even with a queue length of 1, the sending task will never
find the queue full. */
#define mainQUEUE_LENGTH ( 1 )
/*-----------------------------------------------------------*/
/*
* Called by main when mainCREATE_SIMPLE_BLINKY_DEMO_ONLY is set to 1 in
* main.c.
*/
void main_blinky( void );
/*
* The tasks as described in the comments at the top of this file.
*/
static void prvQueueReceiveTask( void *pvParameters );
static void prvQueueSendTask( void *pvParameters );
/*-----------------------------------------------------------*/
/* The queue used by both tasks. */
static QueueHandle_t xQueue = NULL;
/*-----------------------------------------------------------*/
void main_blinky( void )
{
/* Create the queue. */
xQueue = xQueueCreate( mainQUEUE_LENGTH, sizeof( uint32_t ) );
if( xQueue != NULL )
{
/* Start the two tasks as described in the comments at the top of this
file. */
xTaskCreate( prvQueueReceiveTask, /* The function that implements the task. */
"Rx", /* The text name assigned to the task - for debug only as it is not used by the kernel. */
configMINIMAL_STACK_SIZE, /* The size of the stack to allocate to the task. */
NULL, /* The parameter passed to the task - not used in this case. */
mainQUEUE_RECEIVE_TASK_PRIORITY, /* The priority assigned to the task. */
NULL ); /* The task handle is not required, so NULL is passed. */
xTaskCreate( prvQueueSendTask, "TX", configMINIMAL_STACK_SIZE, NULL, mainQUEUE_SEND_TASK_PRIORITY, NULL );
/* Start the tasks and timer running. */
vTaskStartScheduler();
}
/* If all is well, the scheduler will now be running, and the following
line will never be reached. If the following line does execute, then
there was insufficient FreeRTOS heap memory available for the Idle and/or
timer tasks to be created. See the memory management section on the
FreeRTOS web site for more details on the FreeRTOS heap
http://www.freertos.org/a00111.html. */
for( ;; );
}
/*-----------------------------------------------------------*/
static void prvQueueSendTask( void *pvParameters )
{
TickType_t xNextWakeTime;
const unsigned long ulValueToSend = 100UL;
BaseType_t xReturned;
/* Remove compiler warning about unused parameter. */
( void ) pvParameters;
/* Initialise xNextWakeTime - this only needs to be done once. */
xNextWakeTime = xTaskGetTickCount();
for( ;; )
{
/* Place this task in the blocked state until it is time to run again. */
vTaskDelayUntil( &xNextWakeTime, mainQUEUE_SEND_FREQUENCY_MS );
/* Send to the queue - causing the queue receive task to unblock and
toggle the LED. 0 is used as the block time so the sending operation
will not block - it shouldn't need to block as the queue should always
be empty at this point in the code. */
xReturned = xQueueSend( xQueue, &ulValueToSend, 0U );
configASSERT( xReturned == pdPASS );
}
}
/*-----------------------------------------------------------*/
static void prvQueueReceiveTask( void *pvParameters )
{
unsigned long ulReceivedValue;
const unsigned long ulExpectedValue = 100UL;
extern void vToggleLED( void );
/* Remove compiler warning about unused parameter. */
( void ) pvParameters;
for( ;; )
{
/* Wait until something arrives in the queue - this task will block
indefinitely provided INCLUDE_vTaskSuspend is set to 1 in
FreeRTOSConfig.h. */
xQueueReceive( xQueue, &ulReceivedValue, portMAX_DELAY );
/* To get here something must have been received from the queue, but
is it the expected value? If it is, toggle the LED. */
if( ulReceivedValue == ulExpectedValue )
{
vToggleLED();
ulReceivedValue = 0U;
}
}
}
/*-----------------------------------------------------------*/
/*
* FreeRTOS V202104.00
* Copyright (C) 2020 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!
*/
/******************************************************************************
* NOTE 1: This project provides two demo applications. A simple blinky
* style project, and a more comprehensive test and demo application. The
* mainCREATE_SIMPLE_BLINKY_DEMO_ONLY setting in main.c is used to select
* between the two. See the notes on using mainCREATE_SIMPLE_BLINKY_DEMO_ONLY
* in main.c. This file implements the simply blinky style version.
*
* NOTE 2: This file only contains the source code that is specific to the
* blinky demo. Generic functions, such FreeRTOS hook functions, and functions
* required to configure the hardware are defined in main.c.
******************************************************************************
*
* main_blinky() creates one queue, and two tasks. It then starts the
* scheduler.
*
* The Queue Send Task:
* The queue send task is implemented by the prvQueueSendTask() function in
* this file. prvQueueSendTask() sits in a loop that causes it to repeatedly
* block for 1000 milliseconds, before sending the value 100 to the queue that
* was created within main_blinky(). Once the value is sent, the task loops
* back around to block for another 1000 milliseconds...and so on.
*
* The Queue Receive Task:
* The queue receive task is implemented by the prvQueueReceiveTask() function
* in this file. prvQueueReceiveTask() sits in a loop where it repeatedly
* blocks on attempts to read data from the queue that was created within
* main_blinky(). When data is received, the task checks the value of the
* data, and if the value equals the expected 100, toggles an LED. The 'block
* time' parameter passed to the queue receive function specifies that the task
* should be held in the Blocked state indefinitely to wait for data to be
* available on the queue. The queue receive task will only leave the Blocked
* state when the queue send task writes to the queue. As the queue send task
* writes to the queue every 1000 milliseconds, the queue receive task leaves
* the Blocked state every 1000 milliseconds, and therefore toggles the LED
* every 200 milliseconds.
*/
/* Standard includes. */
#include <stdio.h>
#include <string.h>
#include <unistd.h>
/* Kernel includes. */
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
/* Priorities used by the tasks. */
#define mainQUEUE_RECEIVE_TASK_PRIORITY ( tskIDLE_PRIORITY + 2 )
#define mainQUEUE_SEND_TASK_PRIORITY ( tskIDLE_PRIORITY + 1 )
/* The rate at which data is sent to the queue. The 200ms value is converted
to ticks using the pdMS_TO_TICKS() macro. */
#define mainQUEUE_SEND_FREQUENCY_MS pdMS_TO_TICKS( 1000 )
/* The maximum number items the queue can hold. The priority of the receiving
task is above the priority of the sending task, so the receiving task will
preempt the sending task and remove the queue items each time the sending task
writes to the queue. Therefore the queue will never have more than one item in
it at any time, and even with a queue length of 1, the sending task will never
find the queue full. */
#define mainQUEUE_LENGTH ( 1 )
/*-----------------------------------------------------------*/
/*
* Called by main when mainCREATE_SIMPLE_BLINKY_DEMO_ONLY is set to 1 in
* main.c.
*/
void main_blinky( void );
/*
* The tasks as described in the comments at the top of this file.
*/
static void prvQueueReceiveTask( void *pvParameters );
static void prvQueueSendTask( void *pvParameters );
/*-----------------------------------------------------------*/
/* The queue used by both tasks. */
static QueueHandle_t xQueue = NULL;
/*-----------------------------------------------------------*/
void main_blinky( void )
{
/* Create the queue. */
xQueue = xQueueCreate( mainQUEUE_LENGTH, sizeof( uint32_t ) );
if( xQueue != NULL )
{
/* Start the two tasks as described in the comments at the top of this
file. */
xTaskCreate( prvQueueReceiveTask, /* The function that implements the task. */
"Rx", /* The text name assigned to the task - for debug only as it is not used by the kernel. */
configMINIMAL_STACK_SIZE, /* The size of the stack to allocate to the task. */
NULL, /* The parameter passed to the task - not used in this case. */
mainQUEUE_RECEIVE_TASK_PRIORITY, /* The priority assigned to the task. */
NULL ); /* The task handle is not required, so NULL is passed. */
xTaskCreate( prvQueueSendTask, "TX", configMINIMAL_STACK_SIZE, NULL, mainQUEUE_SEND_TASK_PRIORITY, NULL );
/* Start the tasks and timer running. */
vTaskStartScheduler();
}
/* If all is well, the scheduler will now be running, and the following
line will never be reached. If the following line does execute, then
there was insufficient FreeRTOS heap memory available for the Idle and/or
timer tasks to be created. See the memory management section on the
FreeRTOS web site for more details on the FreeRTOS heap
http://www.freertos.org/a00111.html. */
for( ;; );
}
/*-----------------------------------------------------------*/
static void prvQueueSendTask( void *pvParameters )
{
TickType_t xNextWakeTime;
const unsigned long ulValueToSend = 100UL;
BaseType_t xReturned;
/* Remove compiler warning about unused parameter. */
( void ) pvParameters;
/* Initialise xNextWakeTime - this only needs to be done once. */
xNextWakeTime = xTaskGetTickCount();
for( ;; )
{
/* Place this task in the blocked state until it is time to run again. */
vTaskDelayUntil( &xNextWakeTime, mainQUEUE_SEND_FREQUENCY_MS );
/* Send to the queue - causing the queue receive task to unblock and
toggle the LED. 0 is used as the block time so the sending operation
will not block - it shouldn't need to block as the queue should always
be empty at this point in the code. */
xReturned = xQueueSend( xQueue, &ulValueToSend, 0U );
configASSERT( xReturned == pdPASS );
}
}
/*-----------------------------------------------------------*/
static void prvQueueReceiveTask( void *pvParameters )
{
unsigned long ulReceivedValue;
const unsigned long ulExpectedValue = 100UL;
extern void vToggleLED( void );
/* Remove compiler warning about unused parameter. */
( void ) pvParameters;
for( ;; )
{
/* Wait until something arrives in the queue - this task will block
indefinitely provided INCLUDE_vTaskSuspend is set to 1 in
FreeRTOSConfig.h. */
xQueueReceive( xQueue, &ulReceivedValue, portMAX_DELAY );
/* To get here something must have been received from the queue, but
is it the expected value? If it is, toggle the LED. */
if( ulReceivedValue == ulExpectedValue )
{
vToggleLED();
ulReceivedValue = 0U;
}
}
}
/*-----------------------------------------------------------*/
@@ -0,0 +1,13 @@
HiFive1 Rev B is a low-cost, Arduino-compatible development board featuring the Freedom E310. Its the best way to start prototyping and developing your RISCV applications.
This target is ideal for getting familiar with the RISC-V ISA instruction set and the freedom-metal libraries. It supports:
- 1 hart with RV32IMAC core
- 4 hardware breakpoints
- Physical Memory Protection with 8 regions
- 16 local interrupts signal that can be connected to off core complex devices
- Up to 127 PLIC interrupt signals that can be connected to off core complex devices, with 7 priority levels
- GPIO memory with 16 interrupt lines
- SPI memory with 1 interrupt line
- Serial port with 1 interrupt line
- 1 RGB LEDS
@@ -0,0 +1,262 @@
/dts-v1/;
/ {
#address-cells = <1>;
#size-cells = <1>;
compatible = "sifive,hifive1-revb";
model = "sifive,hifive1-revb";
cpus {
#address-cells = <1>;
#size-cells = <0>;
compatible = "sifive,fe310-g000";
L6: cpu@0 {
clocks = <&hfclk>;
compatible = "sifive,rocket0", "riscv";
device_type = "cpu";
i-cache-block-size = <64>;
i-cache-sets = <128>;
i-cache-size = <16384>;
next-level-cache = <&spi0>;
reg = <0>;
riscv,isa = "rv32imac";
riscv,pmpregions = <8>;
sifive,itim = <&itim>;
sifive,dtim = <&dtim>;
status = "okay";
timebase-frequency = <16000000>;
hardware-exec-breakpoint-count = <4>;
hlic: interrupt-controller {
#interrupt-cells = <1>;
compatible = "riscv,cpu-intc";
interrupt-controller;
};
};
};
soc {
#address-cells = <1>;
#size-cells = <1>;
#clock-cells = <1>;
compatible = "sifive,hifive1";
ranges;
hfxoscin: clock@0 {
#clock-cells = <0>;
compatible = "fixed-clock";
clock-frequency = <16000000>;
};
hfxoscout: clock@1 {
compatible = "sifive,fe310-g000,hfxosc";
clocks = <&hfxoscin>;
reg = <&prci 0x4>;
reg-names = "config";
};
hfroscin: clock@2 {
#clock-cells = <0>;
compatible = "fixed-clock";
clock-frequency = <72000000>;
};
hfroscout: clock@3 {
compatible = "sifive,fe310-g000,hfrosc";
clocks = <&hfroscin>;
reg = <&prci 0x0>;
reg-names = "config";
};
hfclk: clock@4 {
compatible = "sifive,fe310-g000,pll";
clocks = <&hfxoscout &hfroscout>;
clock-names = "pllref", "pllsel0";
reg = <&prci 0x8 &prci 0xc>;
reg-names = "config", "divider";
clock-frequency = <16000000>;
};
lfrosc: clock@5 {
#clock-cells = <0>;
compatible = "fixed-clock";
clock-frequency = <32768>;
};
psdlfaltclk: clock@6 {
#clock-cells = <0>;
compatible = "fixed-clock";
clock-frequency = <32768>;
};
lfclk: clock@7 {
compatible = "sifive,fe310-g000,lfrosc";
clocks = <&lfrosc &psdlfaltclk>;
clock-names = "lfrosc", "psdlfaltclk";
reg = <&aon 0x70 &aon 0x7C>;
reg-names = "config", "mux";
};
debug-controller@0 {
compatible = "sifive,debug-011", "riscv,debug-011";
interrupts-extended = <&hlic 65535>;
reg = <0x0 0x1000>;
reg-names = "control";
};
/* Missing: Error device */
maskrom@1000 {
reg = <0x1000 0x2000>;
reg-names = "mem";
};
otp@20000 {
reg = <0x20000 0x2000 0x10010000 0x1000>;
reg-names = "mem", "control";
};
clint: clint@2000000 {
compatible = "riscv,clint0";
interrupts-extended = <&hlic 3 &hlic 7>;
reg = <0x2000000 0x10000>;
reg-names = "control";
};
itim: itim@8000000 {
compatible = "sifive,itim0";
reg = <0x8000000 0x2000>;
reg-names = "mem";
};
plic: interrupt-controller@c000000 {
#interrupt-cells = <1>;
compatible = "riscv,plic0";
interrupt-controller;
interrupts-extended = <&hlic 11>;
reg = <0xc000000 0x4000000>;
reg-names = "control";
riscv,max-priority = <7>;
riscv,ndev = <52>;
};
aon: aon@10000000 {
compatible = "sifive,aon0";
reg = <0x10000000 0x8000>;
reg-names = "mem";
interrupt-parent = <&plic>;
interrupts = <1 2>;
clocks = <&lfclk>;
};
prci: prci@10008000 {
compatible = "sifive,fe310-g000,prci";
reg = <0x10008000 0x8000>;
reg-names = "mem";
};
gpio0: gpio@10012000 {
compatible = "sifive,gpio0";
interrupt-parent = <&plic>;
interrupts = <8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
23 24 25 26 27 28 29 30 31 32 33 34 35 36
27 28 29>;
reg = <0x10012000 0x1000>;
reg-names = "control";
};
led@0 {
compatible = "sifive,gpio-leds";
label = "LD0red";
gpios = <&gpio0 22>;
linux,default-trigger = "none";
};
led@1 {
compatible = "sifive,gpio-leds";
label = "LD0green";
gpios = <&gpio0 19>;
linux,default-trigger = "none";
};
led@2 {
compatible = "sifive,gpio-leds";
label = "LD0blue";
gpios = <&gpio0 21>;
linux,default-trigger = "none";
};
uart0: serial@10013000 {
compatible = "sifive,uart0";
interrupt-parent = <&plic>;
interrupts = <3>;
reg = <0x10013000 0x1000>;
reg-names = "control";
clocks = <&hfclk>;
pinmux = <&gpio0 0x0 0x30000>;
};
spi0: spi@10014000 {
compatible = "sifive,spi0";
interrupt-parent = <&plic>;
interrupts = <5>;
reg = <0x10014000 0x1000 0x20000000 0x7A120>;
reg-names = "control", "mem";
clocks = <&hfclk>;
pinmux = <&gpio0 0x0 0x0>;
#address-cells = <1>;
#size-cells = <1>;
flash@0 {
compatible = "jedec,spi-nor";
reg = <0x20000000 0x424000>;
};
};
pwm0: pwm@10015000 {
compatible = "sifive,pwm0";
sifive,comparator-widthbits = <8>;
sifive,ncomparators = <4>;
interrupt-parent = <&plic>;
interrupts = <40 41 42 43>;
reg = <0x10015000 0x1000>;
reg-names = "control";
clocks = <&hfclk>;
pinmux = <&gpio0 0x0F 0x0F>;
};
i2c0: i2c@10016000 {
compatible = "sifive,i2c0";
interrupt-parent = <&plic>;
interrupts = <52>;
reg = <0x10016000 0x1000>;
reg-names = "control";
clocks = <&hfclk>;
pinmux = <&gpio0 0x0 0x3000>;
};
uart1: serial@10023000 {
compatible = "sifive,uart0";
interrupt-parent = <&plic>;
interrupts = <4>;
reg = <0x10023000 0x1000>;
reg-names = "control";
clocks = <&hfclk>;
pinmux = <&gpio0 0x0 0x840000>;
};
spi1: spi@10024000 {
compatible = "sifive,spi0";
interrupt-parent = <&plic>;
interrupts = <6>;
reg = <0x10024000 0x1000>;
reg-names = "control";
clocks = <&hfclk>;
pinmux = <&gpio0 0x0 0x0003C>;
};
pwm1: pwm@10025000 {
compatible = "sifive,pwm0";
sifive,comparator-widthbits = <16>;
sifive,ncomparators = <4>;
interrupt-parent = <&plic>;
interrupts = <44 45 46 47>;
reg = <0x10025000 0x1000>;
reg-names = "control";
clocks = <&hfclk>;
pinmux = <&gpio0 0x780000 0x780000>;
};
spi2: spi@10034000 {
compatible = "sifive,spi0";
interrupt-parent = <&plic>;
interrupts = <7>;
reg = <0x10034000 0x1000>;
reg-names = "control";
clocks = <&hfclk>;
pinmux = <&gpio0 0x0 0xFC000000>;
};
pwm2: pwm@10035000 {
compatible = "sifive,pwm0";
sifive,comparator-widthbits = <16>;
sifive,ncomparators = <4>;
interrupt-parent = <&plic>;
interrupts = <48 49 50 51>;
reg = <0x10035000 0x1000>;
reg-names = "control";
clocks = <&hfclk>;
pinmux = <&gpio0 0x3C00 0x3C00>;
};
dtim: dtim@80000000 {
compatible = "sifive,dtim0";
reg = <0x80000000 0x4000>;
reg-names = "mem";
};
};
};
@@ -1,209 +1,10 @@
/dts-v1/;
/include/ "core.dts"
/ {
#address-cells = <1>;
#size-cells = <1>;
compatible = "sifive,hifive1-revb";
model = "sifive,hifive1-revb";
chosen {
stdout-path = "/soc/serial@10013000:115200";
metal,entry = <&spi0 0x10000>;
};
cpus {
#address-cells = <1>;
#size-cells = <0>;
compatible = "sifive,fe310-g000";
L6: cpu@0 {
clocks = <&hfclk>;
compatible = "sifive,rocket0", "riscv";
device_type = "cpu";
i-cache-block-size = <64>;
i-cache-sets = <128>;
i-cache-size = <16384>;
next-level-cache = <&spi0>;
reg = <0>;
riscv,isa = "rv32imac";
riscv,pmpregions = <8>;
sifive,dtim = <&dtim>;
status = "okay";
timebase-frequency = <1000000>;
hardware-exec-breakpoint-count = <4>;
hlic: interrupt-controller {
#interrupt-cells = <1>;
compatible = "riscv,cpu-intc";
interrupt-controller;
};
};
};
soc {
#address-cells = <1>;
#size-cells = <1>;
#clock-cells = <1>;
compatible = "sifive,hifive1";
ranges;
hfxoscin: clock@0 {
#clock-cells = <0>;
compatible = "fixed-clock";
clock-frequency = <16000000>;
};
hfxoscout: clock@1 {
compatible = "sifive,fe310-g000,hfxosc";
clocks = <&hfxoscin>;
reg = <&prci 0x4>;
reg-names = "config";
};
hfroscin: clock@2 {
#clock-cells = <0>;
compatible = "fixed-clock";
clock-frequency = <72000000>;
};
hfroscout: clock@3 {
compatible = "sifive,fe310-g000,hfrosc";
clocks = <&hfroscin>;
reg = <&prci 0x0>;
reg-names = "config";
};
hfclk: clock@4 {
compatible = "sifive,fe310-g000,pll";
clocks = <&hfxoscout &hfroscout>;
clock-names = "pllref", "pllsel0";
reg = <&prci 0x8 &prci 0xc>;
reg-names = "config", "divider";
clock-frequency = <16000000>;
};
lfroscin: clock@5 {
#clock-cells = <0>;
compatible = "fixed-clock";
clock-frequency = <32000000>;
};
lfclk: clock@6 {
compatible = "sifive,fe310-g000,lfrosc";
clocks = <&lfroscin>;
reg = <&aon 0x70>;
reg-names = "config";
};
aon: aon@10000000 {
compatible = "sifive,aon0";
reg = <0x10000000 0x8000>;
reg-names = "mem";
};
prci: prci@10008000 {
compatible = "sifive,fe310-g000,prci";
reg = <0x10008000 0x8000>;
reg-names = "mem";
};
clint: clint@2000000 {
compatible = "riscv,clint0";
interrupts-extended = <&hlic 3 &hlic 7>;
reg = <0x2000000 0x10000>;
reg-names = "control";
};
local-external-interrupts-0 {
compatible = "sifive,local-external-interrupts0";
interrupt-parent = <&hlic>;
interrupts = <16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31>;
};
plic: interrupt-controller@c000000 {
#interrupt-cells = <1>;
compatible = "riscv,plic0";
interrupt-controller;
interrupts-extended = <&hlic 11>;
reg = <0xc000000 0x4000000>;
reg-names = "control";
riscv,max-priority = <7>;
riscv,ndev = <26>;
};
global-external-interrupts {
compatile = "sifive,global-external-interrupts0";
interrupt-parent = <&plic>;
interrupts = <1 2 3 4>;
};
debug-controller@0 {
compatible = "sifive,debug-011", "riscv,debug-011";
interrupts-extended = <&hlic 65535>;
reg = <0x0 0x100>;
reg-names = "control";
};
maskrom@1000 {
reg = <0x1000 0x2000>;
reg-names = "mem";
};
otp@20000 {
reg = <0x20000 0x2000 0x10010000 0x1000>;
reg-names = "mem", "control";
};
dtim: dtim@80000000 {
compatible = "sifive,dtim0";
reg = <0x80000000 0x4000>;
reg-names = "mem";
};
pwm@10015000 {
compatible = "sifive,pwm0";
interrupt-parent = <&plic>;
interrupts = <23 24 25 26>;
reg = <0x10015000 0x1000>;
reg-names = "control";
};
gpio0: gpio@10012000 {
compatible = "sifive,gpio0";
interrupt-parent = <&plic>;
interrupts = <7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22>;
reg = <0x10012000 0x1000>;
reg-names = "control";
};
uart0: serial@10013000 {
compatible = "sifive,uart0";
interrupt-parent = <&plic>;
interrupts = <5>;
reg = <0x10013000 0x1000>;
reg-names = "control";
clocks = <&hfclk>;
pinmux = <&gpio0 0x30000 0x30000>;
};
spi0: spi@10014000 {
compatible = "sifive,spi0";
interrupt-parent = <&plic>;
interrupts = <6>;
reg = <0x10014000 0x1000 0x20000000 0x7A120>;
reg-names = "control", "mem";
clocks = <&hfclk>;
pinmux = <&gpio0 0x0003C 0x0003C>;
};
i2c0: i2c@10016000 {
compatible = "sifive,i2c0";
interrupt-parent = <&plic>;
interrupts = <52>;
reg = <0x10016000 0x1000>;
reg-names = "control";
};
led@0red {
compatible = "sifive,gpio-leds";
label = "LD0red";
gpios = <&gpio0 22>;
linux,default-trigger = "none";
};
led@0green {
compatible = "sifive,gpio-leds";
label = "LD0green";
gpios = <&gpio0 19>;
linux,default-trigger = "none";
};
led@0blue {
compatible = "sifive,gpio-leds";
label = "LD0blue";
gpios = <&gpio0 21>;
linux,default-trigger = "none";
};
};
chosen {
metal,entry = <&spi0 1 65536>;
metal,boothart = <&L6>;
stdout-path = "/soc/serial@10013000:115200";
metal,itim = <&itim 0 0>;
metal,ram = <&dtim 0 0>;
};
};
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,259 @@
/* Copyright 2019 SiFive, Inc */
/* SPDX-License-Identifier: Apache-2.0 */
#ifndef METAL__ATOMIC_H
#define METAL__ATOMIC_H
#include <stdint.h>
#include <metal/compiler.h>
typedef volatile int32_t metal_atomic_t;
#define METAL_ATOMIC_DECLARE(name) \
__attribute((section(".data.atomics"))) metal_atomic_t name
#define _METAL_STORE_AMO_ACCESS_FAULT 7
/* This macro stores the memory address in mtval like a normal store/amo access
* fault, triggers a trap, and then if execution returns, returns 0 as an
* arbitrary choice */
#define _METAL_TRAP_AMO_ACCESS(addr) \
__asm__("csrw mtval, %[atomic]" ::[atomic] "r"(a)); \
_metal_trap(_METAL_STORE_AMO_ACCESS_FAULT); \
return 0;
/*!
* @brief Check if the platform supports atomic operations
*
* @return 1 if atomic operations are supported, 0 if not
*/
__inline__ int32_t metal_atomic_available(void) {
#ifdef __riscv_atomic
return 1;
#else
return 0;
#endif
}
/*!
* @brief Atomically increment a metal_atomic_t and return its old value
*
* If atomics are not supported on the platform, this function will trap with
* a Store/AMO access fault.
*
* @param a The pointer to the value to increment
* @param increment the amount to increment the value
*
* @return The previous value of the metal_atomic_t
*/
__inline__ int32_t metal_atomic_add(metal_atomic_t *a, int32_t increment) {
#ifdef __riscv_atomic
int32_t old;
__asm__ volatile("amoadd.w %[old], %[increment], (%[atomic])"
: [old] "=r"(old)
: [increment] "r"(increment), [atomic] "r"(a)
: "memory");
return old;
#else
_METAL_TRAP_AMO_ACCESS(a);
#endif
}
/*!
* @brief Atomically bitwise-AND a metal_atomic_t and return its old value
*
* If atomics are not supported on the platform, this function will trap with
* a Store/AMO access fault.
*
* @param a The pointer to the value to bitwise-AND
* @param mask the bitmask to AND
*
* @return The previous value of the metal_atomic_t
*/
__inline__ int32_t metal_atomic_and(metal_atomic_t *a, int32_t mask) {
#ifdef __riscv_atomic
int32_t old;
__asm__ volatile("amoand.w %[old], %[mask], (%[atomic])"
: [old] "=r"(old)
: [mask] "r"(mask), [atomic] "r"(a)
: "memory");
return old;
#else
_METAL_TRAP_AMO_ACCESS(a);
#endif
}
/*!
* @brief Atomically bitwise-OR a metal_atomic_t and return its old value
*
* If atomics are not supported on the platform, this function will trap with
* a Store/AMO access fault.
*
* @param a The pointer to the value to bitwise-OR
* @param mask the bitmask to OR
*
* @return The previous value of the metal_atomic_t
*/
__inline__ int32_t metal_atomic_or(metal_atomic_t *a, int32_t mask) {
#ifdef __riscv_atomic
int32_t old;
__asm__ volatile("amoor.w %[old], %[mask], (%[atomic])"
: [old] "=r"(old)
: [mask] "r"(mask), [atomic] "r"(a)
: "memory");
return old;
#else
_METAL_TRAP_AMO_ACCESS(a);
#endif
}
/*!
* @brief Atomically swap a metal_atomic_t and return its old value
*
* If atomics are not supported on the platform, this function will trap with
* a Store/AMO access fault.
*
* @param a The pointer to the value to swap
* @param new_value the value to store in the metal_atomic_t
*
* @return The previous value of the metal_atomic_t
*/
__inline__ int32_t metal_atomic_swap(metal_atomic_t *a, int32_t new_value) {
#ifdef __riscv_atomic
int32_t old;
__asm__ volatile("amoswap.w %[old], %[newval], (%[atomic])"
: [old] "=r"(old)
: [newval] "r"(new_value), [atomic] "r"(a)
: "memory");
return old;
#else
_METAL_TRAP_AMO_ACCESS(a);
#endif
}
/*!
* @brief Atomically bitwise-XOR a metal_atomic_t and return its old value
*
* If atomics are not supported on the platform, this function will trap with
* a Store/AMO access fault.
*
* @param a The pointer to the value to bitwise-XOR
* @param mask the bitmask to XOR
*
* @return The previous value of the metal_atomic_t
*/
__inline__ int32_t metal_atomic_xor(metal_atomic_t *a, int32_t mask) {
#ifdef __riscv_atomic
int32_t old;
__asm__ volatile("amoxor.w %[old], %[mask], (%[atomic])"
: [old] "=r"(old)
: [mask] "r"(mask), [atomic] "r"(a)
: "memory");
return old;
#else
_METAL_TRAP_AMO_ACCESS(a);
#endif
}
/*!
* @brief Atomically set the value of a memory location to the greater of
* its current value or a value to compare it with.
*
* If atomics are not supported on the platform, this function will trap with
* a Store/AMO access fault.
*
* @param a The pointer to the value to swap
* @param compare the value to compare with the value in memory
*
* @return The previous value of the metal_atomic_t
*/
__inline__ int32_t metal_atomic_max(metal_atomic_t *a, int32_t compare) {
#ifdef __riscv_atomic
int32_t old;
__asm__ volatile("amomax.w %[old], %[compare], (%[atomic])"
: [old] "=r"(old)
: [compare] "r"(compare), [atomic] "r"(a)
: "memory");
return old;
#else
_METAL_TRAP_AMO_ACCESS(a);
#endif
}
/*!
* @brief Atomically set the value of a memory location to the (unsigned)
* greater of its current value or a value to compare it with.
*
* If atomics are not supported on the platform, this function will trap with
* a Store/AMO access fault.
*
* @param a The pointer to the value to swap
* @param compare the value to compare with the value in memory
*
* @return The previous value of the metal_atomic_t
*/
__inline__ uint32_t metal_atomic_max_u(metal_atomic_t *a, uint32_t compare) {
#ifdef __riscv_atomic
int32_t old;
__asm__ volatile("amomaxu.w %[old], %[compare], (%[atomic])"
: [old] "=r"(old)
: [compare] "r"(compare), [atomic] "r"(a)
: "memory");
return old;
#else
_METAL_TRAP_AMO_ACCESS(a);
#endif
}
/*!
* @brief Atomically set the value of a memory location to the lesser of
* its current value or a value to compare it with.
*
* If atomics are not supported on the platform, this function will trap with
* a Store/AMO access fault.
*
* @param a The pointer to the value to swap
* @param compare the value to compare with the value in memory
*
* @return The previous value of the metal_atomic_t
*/
__inline__ int32_t metal_atomic_min(metal_atomic_t *a, int32_t compare) {
#ifdef __riscv_atomic
int32_t old;
__asm__ volatile("amomin.w %[old], %[compare], (%[atomic])"
: [old] "=r"(old)
: [compare] "r"(compare), [atomic] "r"(a)
: "memory");
return old;
#else
_METAL_TRAP_AMO_ACCESS(a);
#endif
}
/*!
* @brief Atomically set the value of a memory location to the (unsigned) lesser
* of its current value or a value to compare it with.
*
* If atomics are not supported on the platform, this function will trap with
* a Store/AMO access fault.
*
* @param a The pointer to the value to swap
* @param compare the value to compare with the value in memory
*
* @return The previous value of the metal_atomic_t
*/
__inline__ uint32_t metal_atomic_min_u(metal_atomic_t *a, uint32_t compare) {
#ifdef __riscv_atomic
int32_t old;
__asm__ volatile("amominu.w %[old], %[compare], (%[atomic])"
: [old] "=r"(old)
: [compare] "r"(compare), [atomic] "r"(a)
: "memory");
return old;
#else
_METAL_TRAP_AMO_ACCESS(a);
#endif
}
#endif /* METAL__ATOMIC_H */
@@ -15,7 +15,8 @@ struct metal_button;
struct metal_button_vtable {
int (*button_exist)(struct metal_button *button, char *label);
struct metal_interrupt* (*interrupt_controller)(struct metal_button *button);
struct metal_interrupt *(*interrupt_controller)(
struct metal_button *button);
int (*get_interrupt_id)(struct metal_button *button);
};
@@ -35,8 +36,7 @@ struct metal_button {
* @param label The DeviceTree label for the button
* @return A handle for the button
*/
struct metal_button* metal_button_get(char *label);
struct metal_button *metal_button_get(char *label);
/*!
* @brief Get the interrupt controller for a button
@@ -45,8 +45,10 @@ struct metal_button* metal_button_get(char *label);
* @return A pointer to the interrupt controller responsible for handling
* button interrupts.
*/
inline struct metal_interrupt*
metal_button_interrupt_controller(struct metal_button *button) { return button->vtable->interrupt_controller(button); }
__inline__ struct metal_interrupt *
metal_button_interrupt_controller(struct metal_button *button) {
return button->vtable->interrupt_controller(button);
}
/*!
* @brief Get the interrupt id for a button
@@ -54,6 +56,8 @@ inline struct metal_interrupt*
* @param button The handle for the button
* @return The interrupt id corresponding to a button.
*/
inline int metal_button_get_interrupt_id(struct metal_button *button) { return button->vtable->get_interrupt_id(button); }
__inline__ int metal_button_get_interrupt_id(struct metal_button *button) {
return button->vtable->get_interrupt_id(button);
}
#endif
@@ -1,4 +1,4 @@
/* Copyright 2018 SiFive, Inc */
/* Copyright 2020 SiFive, Inc */
/* SPDX-License-Identifier: Apache-2.0 */
#ifndef METAL__CACHE_H
@@ -9,40 +9,58 @@
*
* @brief API for configuring caches
*/
struct metal_cache;
struct __metal_cache_vtable {
void (*init)(struct metal_cache *cache, int ways);
int (*get_enabled_ways)(struct metal_cache *cache);
int (*set_enabled_ways)(struct metal_cache *cache, int ways);
};
#include <stdint.h>
/*!
* @brief a handle for a cache
* Note: To be deprecated in next release.
*/
struct metal_cache {
const struct __metal_cache_vtable *vtable;
uint8_t __no_empty_structs;
};
/*!
* @brief Initialize L2 cache controller.
* Enables all available cache ways.
* @param None
* @return 0 If no error
*/
int metal_l2cache_init(void);
/*!
* @brief Get the current number of enabled L2 cache ways
* @param None
* @return The current number of enabled L2 cache ways
*/
int metal_l2cache_get_enabled_ways(void);
/*!
* @brief Enable the requested number of L2 cache ways
* @param ways Number of ways to enable
* @return 0 if the ways are successfully enabled
*/
int metal_l2cache_set_enabled_ways(int ways);
/*!
* @brief Initialize a cache
* @param cache The handle for the cache to initialize
* @param ways The number of ways to enable
*
* Initializes a cache with the requested number of ways enabled.
* Note: API to be deprecated in next release.
*/
inline void metal_cache_init(struct metal_cache *cache, int ways) {
return cache->vtable->init(cache, ways);
__inline__ void metal_cache_init(struct metal_cache *cache, int ways) {
metal_l2cache_init();
}
/*!
* @brief Get the current number of enabled cache ways
* @param cache The handle for the cache
* @return The current number of enabled cache ways
* Note: API to be deprecated in next release.
*/
inline int metal_cache_get_enabled_ways(struct metal_cache *cache) {
return cache->vtable->get_enabled_ways(cache);
__inline__ int metal_cache_get_enabled_ways(struct metal_cache *cache) {
return metal_l2cache_get_enabled_ways();
}
/*!
@@ -50,9 +68,41 @@ inline int metal_cache_get_enabled_ways(struct metal_cache *cache) {
* @param cache The handle for the cache
* @param ways The number of ways to enabled
* @return 0 if the ways are successfully enabled
* Note: API to be deprecated in next release.
*/
inline int metal_cache_set_enabled_ways(struct metal_cache *cache, int ways) {
return cache->vtable->set_enabled_ways(cache, ways);
__inline__ int metal_cache_set_enabled_ways(struct metal_cache *cache,
int ways) {
return metal_l2cache_set_enabled_ways(ways);
}
/*!
* @brief Check if dcache is supported on the core
* @param hartid The core to check
* @return 1 if dcache is present
*/
int metal_dcache_l1_available(int hartid);
/*!
* @brief Flush dcache for L1 on the requested core with write back
* @param hartid The core to flush
* @param address The virtual address of cacheline to invalidate
* @return None
*/
void metal_dcache_l1_flush(int hartid, uintptr_t address);
/*!
* @brief Discard dcache for L1 on the requested core with no write back
* @param hartid The core to discard
* @param address The virtual address of cacheline to invalidate
* @return None
*/
void metal_dcache_l1_discard(int hartid, uintptr_t address);
/*!
* @brief Check if icache is supported on the core
* @param hartid The core to check
* @return 1 if icache is present
*/
int metal_icache_l1_available(int hartid);
#endif
@@ -4,11 +4,12 @@
#ifndef METAL__CLOCK_H
#define METAL__CLOCK_H
/*!
/*!
* @file clock.h
* @brief API for manipulating clock sources
*
* The clock interface allows for controlling the rate of various clocks in the system.
* The clock interface allows for controlling the rate of various clocks in the
* system.
*/
struct metal_clock;
@@ -22,37 +23,82 @@ struct __metal_clock_vtable {
};
/*!
* @brief Function signature of clock pre-rate change callbacks
* @brief Function signature of clock rate change callbacks
*/
typedef void (*metal_clock_pre_rate_change_callback)(void *priv);
typedef void (*metal_clock_rate_change_callback)(void *priv);
struct _metal_clock_callback_t;
struct _metal_clock_callback_t {
/* The callback function */
metal_clock_rate_change_callback callback;
/* Private data for the callback function */
void *priv;
struct _metal_clock_callback_t *_next;
};
/*!
* @brief Function signature of clock post-rate change callbacks
* @brief Type for the linked list of callbacks for clock rate changes
*/
typedef void (*metal_clock_post_rate_change_callback)(void *priv);
typedef struct _metal_clock_callback_t metal_clock_callback;
/*!
* @brief Call all callbacks in the linked list, if any are registered
*/
__inline__ void
_metal_clock_call_all_callbacks(const metal_clock_callback *const list) {
const metal_clock_callback *current = list;
while (current) {
current->callback(current->priv);
current = current->_next;
}
}
/*!
* @brief Append a callback to the linked list and return the head of the list
*/
__inline__ metal_clock_callback *
_metal_clock_append_to_callbacks(metal_clock_callback *list,
metal_clock_callback *const cb) {
cb->_next = NULL;
if (!list) {
return cb;
}
metal_clock_callback *current = list;
while ((current->_next) != NULL) {
current = current->_next;
}
current->_next = cb;
return list;
}
/*!
* @struct metal_clock
* @brief The handle for a clock
*
* Clocks are defined as a pointer to a `struct metal_clock`, the contents of which
* are implementation defined. Users of the clock interface must call functions
* which accept a `struct metal_clock *` as an argument to interract with the clock.
* Clocks are defined as a pointer to a `struct metal_clock`, the contents of
* which are implementation defined. Users of the clock interface must call
* functions which accept a `struct metal_clock *` as an argument to interract
* with the clock.
*
* Note that no mechanism for obtaining a pointer to a `struct metal_clock` has been
* defined, making it impossible to call any of these functions without invoking
* implementation-defined behavior.
* Note that no mechanism for obtaining a pointer to a `struct metal_clock` has
* been defined, making it impossible to call any of these functions without
* invoking implementation-defined behavior.
*/
struct metal_clock {
const struct __metal_clock_vtable *vtable;
/* Pre-rate change callback */
metal_clock_pre_rate_change_callback _pre_rate_change_callback;
void *_pre_rate_change_callback_priv;
/* Pre-rate change callback linked list */
metal_clock_callback *_pre_rate_change_callback;
/* Post-rate change callback */
metal_clock_post_rate_change_callback _post_rate_change_callback;
void *_post_rate_change_callback_priv;
/* Post-rate change callback linked list */
metal_clock_callback *_post_rate_change_callback;
};
/*!
@@ -61,7 +107,9 @@ struct metal_clock {
* @param clk The handle for the clock
* @return The current rate of the clock in Hz
*/
inline long metal_clock_get_rate_hz(const struct metal_clock *clk) { return clk->vtable->get_rate_hz(clk); }
__inline__ long metal_clock_get_rate_hz(const struct metal_clock *clk) {
return clk->vtable->get_rate_hz(clk);
}
/*!
* @brief Set the current rate of a clock
@@ -74,18 +122,15 @@ inline long metal_clock_get_rate_hz(const struct metal_clock *clk) { return clk-
* to the given rate in Hz. Returns the actual value that's been selected, which
* could be anything!
*
* Prior to and after the rate change of the clock, this will call the registered
* pre- and post-rate change callbacks.
* Prior to and after the rate change of the clock, this will call the
* registered pre- and post-rate change callbacks.
*/
inline long metal_clock_set_rate_hz(struct metal_clock *clk, long hz)
{
if(clk->_pre_rate_change_callback != NULL)
clk->_pre_rate_change_callback(clk->_pre_rate_change_callback_priv);
__inline__ long metal_clock_set_rate_hz(struct metal_clock *clk, long hz) {
_metal_clock_call_all_callbacks(clk->_pre_rate_change_callback);
long out = clk->vtable->set_rate_hz(clk, hz);
if (clk->_post_rate_change_callback != NULL)
clk->_post_rate_change_callback(clk->_post_rate_change_callback_priv);
_metal_clock_call_all_callbacks(clk->_post_rate_change_callback);
return out;
}
@@ -95,12 +140,12 @@ inline long metal_clock_set_rate_hz(struct metal_clock *clk, long hz)
*
* @param clk The handle for the clock
* @param cb The callback to be registered
* @param priv Private data for the callback handler
*/
inline void metal_clock_register_pre_rate_change_callback(struct metal_clock *clk, metal_clock_pre_rate_change_callback cb, void *priv)
{
clk->_pre_rate_change_callback = cb;
clk->_pre_rate_change_callback_priv = priv;
__inline__ void
metal_clock_register_pre_rate_change_callback(struct metal_clock *clk,
metal_clock_callback *cb) {
clk->_pre_rate_change_callback =
_metal_clock_append_to_callbacks(clk->_pre_rate_change_callback, cb);
}
/*!
@@ -108,12 +153,12 @@ inline void metal_clock_register_pre_rate_change_callback(struct metal_clock *cl
*
* @param clk The handle for the clock
* @param cb The callback to be registered
* @param priv Private data for the callback handler
*/
inline void metal_clock_register_post_rate_change_callback(struct metal_clock *clk, metal_clock_post_rate_change_callback cb, void *priv)
{
clk->_post_rate_change_callback = cb;
clk->_post_rate_change_callback_priv = priv;
__inline__ void
metal_clock_register_post_rate_change_callback(struct metal_clock *clk,
metal_clock_callback *cb) {
clk->_post_rate_change_callback =
_metal_clock_append_to_callbacks(clk->_post_rate_change_callback, cb);
}
#endif
@@ -4,18 +4,19 @@
#ifndef METAL__COMPILER_H
#define METAL__COMPILER_H
#define __METAL_DECLARE_VTABLE(type) \
extern const struct type type;
#define __METAL_DECLARE_VTABLE(type) extern const struct type type;
#define __METAL_DEFINE_VTABLE(type) \
const struct type type
#define __METAL_DEFINE_VTABLE(type) const struct type type
#define __METAL_GET_FIELD(reg, mask) \
#define __METAL_GET_FIELD(reg, mask) \
(((reg) & (mask)) / ((mask) & ~((mask) << 1)))
/* Set field with mask for a given value */
#define __METAL_SET_FIELD(reg, mask, val) \
(((reg) & ~(mask)) | (((val) * ((mask) & ~((mask) << 1))) & (mask)))
#define __METAL_SET_FIELD(reg, mask, val) \
(((reg) & ~(mask)) | (((val) * ((mask) & ~((mask) << 1))) & (mask)))
#define __METAL_MIN(a, b) ((a) < (b) ? (a) : (b))
#define __METAL_MAX(a, b) ((a) > (b) ? (a) : (b))
void _metal_trap(int ecode);
@@ -9,33 +9,35 @@
#ifndef METAL__CPU_H
#define METAL__CPU_H
#include <stdint.h>
#include <metal/interrupt.h>
#include <stdint.h>
struct metal_cpu;
/*!
* @brief Function signature for exception handlers
*/
typedef void (*metal_exception_handler_t) (struct metal_cpu *cpu, int ecode);
typedef void (*metal_exception_handler_t)(struct metal_cpu *cpu, int ecode);
struct metal_cpu_vtable {
unsigned long long (*timer_get)(struct metal_cpu *cpu);
unsigned long long (*mcycle_get)(struct metal_cpu *cpu);
unsigned long long (*timebase_get)(struct metal_cpu *cpu);
unsigned long long (*mtime_get)(struct metal_cpu *cpu);
int (*mtimecmp_set)(struct metal_cpu *cpu, unsigned long long time);
struct metal_interrupt* (*tmr_controller_interrupt)(struct metal_cpu *cpu);
struct metal_interrupt *(*tmr_controller_interrupt)(struct metal_cpu *cpu);
int (*get_tmr_interrupt_id)(struct metal_cpu *cpu);
struct metal_interrupt* (*sw_controller_interrupt)(struct metal_cpu *cpu);
struct metal_interrupt *(*sw_controller_interrupt)(struct metal_cpu *cpu);
int (*get_sw_interrupt_id)(struct metal_cpu *cpu);
int (*set_sw_ipi)(struct metal_cpu *cpu, int hartid);
int (*clear_sw_ipi)(struct metal_cpu *cpu, int hartid);
int (*get_msip)(struct metal_cpu *cpu, int hartid);
struct metal_interrupt* (*controller_interrupt)(struct metal_cpu *cpu);
int (*exception_register)(struct metal_cpu *cpu, int ecode, metal_exception_handler_t handler);
struct metal_interrupt *(*controller_interrupt)(struct metal_cpu *cpu);
int (*exception_register)(struct metal_cpu *cpu, int ecode,
metal_exception_handler_t handler);
int (*get_ilen)(struct metal_cpu *cpu, uintptr_t epc);
uintptr_t (*get_epc)(struct metal_cpu *cpu);
int (*set_epc)(struct metal_cpu *cpu, uintptr_t epc);
struct metal_buserror *(*get_buserror)(struct metal_cpu *cpu);
};
/*! @brief A device handle for a CPU hart
@@ -49,17 +51,17 @@ struct metal_cpu {
* @param hartid The ID of the desired CPU hart
* @return A pointer to the CPU device handle
*/
struct metal_cpu* metal_cpu_get(int hartid);
struct metal_cpu *metal_cpu_get(unsigned int hartid);
/*! @brief Get the hartid of the CPU hart executing this function
*
* @return The hartid of the current CPU hart */
int metal_cpu_get_current_hartid();
int metal_cpu_get_current_hartid(void);
/*! @brief Get the number of CPU harts
*
*
* @return The number of CPU harts */
int metal_cpu_get_num_harts();
int metal_cpu_get_num_harts(void);
/*! @brief Get the CPU cycle count timer value
*
@@ -68,8 +70,9 @@ int metal_cpu_get_num_harts();
* @param cpu The CPU device handle
* @return The value of the CPU cycle count timer
*/
inline unsigned long long metal_cpu_get_timer(struct metal_cpu *cpu)
{ return cpu->vtable->timer_get(cpu); }
__inline__ unsigned long long metal_cpu_get_timer(struct metal_cpu *cpu) {
return cpu->vtable->mcycle_get(cpu);
}
/*! @brief Get the timebase of the CPU
*
@@ -78,8 +81,9 @@ inline unsigned long long metal_cpu_get_timer(struct metal_cpu *cpu)
* @param cpu The CPU device handle
* @return The value of the cycle count timer timebase
*/
inline unsigned long long metal_cpu_get_timebase(struct metal_cpu *cpu)
{ return cpu->vtable->timebase_get(cpu); }
__inline__ unsigned long long metal_cpu_get_timebase(struct metal_cpu *cpu) {
return cpu->vtable->timebase_get(cpu);
}
/*! @brief Get the value of the mtime RTC
*
@@ -90,8 +94,9 @@ inline unsigned long long metal_cpu_get_timebase(struct metal_cpu *cpu)
* @param cpu The CPU device handle
* @return The value of mtime, or 0 if failure
*/
inline unsigned long long metal_cpu_get_mtime(struct metal_cpu *cpu)
{ return cpu->vtable->mtime_get(cpu); }
__inline__ unsigned long long metal_cpu_get_mtime(struct metal_cpu *cpu) {
return cpu->vtable->mtime_get(cpu);
}
/*! @brief Set the value of the RTC mtimecmp RTC
*
@@ -103,20 +108,24 @@ inline unsigned long long metal_cpu_get_mtime(struct metal_cpu *cpu)
* @param time The value to set the compare register to
* @return The value of mtimecmp or -1 if error
*/
inline int metal_cpu_set_mtimecmp(struct metal_cpu *cpu, unsigned long long time)
{ return cpu->vtable->mtimecmp_set(cpu, time); }
__inline__ int metal_cpu_set_mtimecmp(struct metal_cpu *cpu,
unsigned long long time) {
return cpu->vtable->mtimecmp_set(cpu, time);
}
/*! @brief Get a reference to RTC timer interrupt controller
*
* Get a reference to the interrupt controller for the real-time clock interrupt.
* The controller returned by this function must be initialized before any interrupts
* are registered or enabled with it.
* Get a reference to the interrupt controller for the real-time clock
* interrupt. The controller returned by this function must be initialized
* before any interrupts are registered or enabled with it.
*
* @param cpu The CPU device handle
* @return A pointer to the timer interrupt handle
*/
inline struct metal_interrupt* metal_cpu_timer_interrupt_controller(struct metal_cpu *cpu)
{ return cpu->vtable->tmr_controller_interrupt(cpu); }
__inline__ struct metal_interrupt *
metal_cpu_timer_interrupt_controller(struct metal_cpu *cpu) {
return cpu->vtable->tmr_controller_interrupt(cpu);
}
/*! @brief Get the RTC timer interrupt id
*
@@ -125,20 +134,23 @@ inline struct metal_interrupt* metal_cpu_timer_interrupt_controller(struct metal
* @param cpu The CPU device handle
* @return The timer interrupt ID
*/
inline int metal_cpu_timer_get_interrupt_id(struct metal_cpu *cpu)
{ return cpu->vtable->get_tmr_interrupt_id(cpu); }
__inline__ int metal_cpu_timer_get_interrupt_id(struct metal_cpu *cpu) {
return cpu->vtable->get_tmr_interrupt_id(cpu);
}
/*! @brief Get a reference to the software interrupt controller
*
* Get a reference to the interrupt controller for the software/inter-process
* interrupt. The controller returned by this function must be initialized before
* any interrupts are registered or enabled with it.
* interrupt. The controller returned by this function must be initialized
* before any interrupts are registered or enabled with it.
*
* @param cpu The CPU device handle
* @return A pointer to the software interrupt handle
*/
inline struct metal_interrupt* metal_cpu_software_interrupt_controller(struct metal_cpu *cpu)
{ return cpu->vtable->sw_controller_interrupt(cpu); }
__inline__ struct metal_interrupt *
metal_cpu_software_interrupt_controller(struct metal_cpu *cpu) {
return cpu->vtable->sw_controller_interrupt(cpu);
}
/*! @brief Get the software interrupt id
*
@@ -147,8 +159,9 @@ inline struct metal_interrupt* metal_cpu_software_interrupt_controller(struct me
* @param cpu The CPU device handle
* @return the software interrupt ID
*/
inline int metal_cpu_software_get_interrupt_id(struct metal_cpu *cpu)
{ return cpu->vtable->get_sw_interrupt_id(cpu); }
__inline__ int metal_cpu_software_get_interrupt_id(struct metal_cpu *cpu) {
return cpu->vtable->get_sw_interrupt_id(cpu);
}
/*!
* @brief Set the inter-process interrupt for a hart
@@ -161,8 +174,9 @@ inline int metal_cpu_software_get_interrupt_id(struct metal_cpu *cpu)
* @param hartid The CPU hart ID to be interrupted
* @return 0 upon success
*/
inline int metal_cpu_software_set_ipi(struct metal_cpu *cpu, int hartid)
{ return cpu->vtable->set_sw_ipi(cpu, hartid); }
__inline__ int metal_cpu_software_set_ipi(struct metal_cpu *cpu, int hartid) {
return cpu->vtable->set_sw_ipi(cpu, hartid);
}
/*!
* @brief Clear the inter-process interrupt for a hart
@@ -175,8 +189,9 @@ inline int metal_cpu_software_set_ipi(struct metal_cpu *cpu, int hartid)
* @param hartid The CPU hart ID to clear
* @return 0 upon success
*/
inline int metal_cpu_software_clear_ipi(struct metal_cpu *cpu, int hartid)
{ return cpu->vtable->clear_sw_ipi(cpu, hartid); }
__inline__ int metal_cpu_software_clear_ipi(struct metal_cpu *cpu, int hartid) {
return cpu->vtable->clear_sw_ipi(cpu, hartid);
}
/*!
* @brief Get the value of MSIP for the given hart
@@ -190,8 +205,9 @@ inline int metal_cpu_software_clear_ipi(struct metal_cpu *cpu, int hartid)
* @param hartid The CPU hart to read
* @return 0 upon success
*/
inline int metal_cpu_get_msip(struct metal_cpu *cpu, int hartid)
{ return cpu->vtable->get_msip(cpu, hartid); }
__inline__ int metal_cpu_get_msip(struct metal_cpu *cpu, int hartid) {
return cpu->vtable->get_msip(cpu, hartid);
}
/*!
* @brief Get the interrupt controller for the CPU
@@ -204,22 +220,26 @@ inline int metal_cpu_get_msip(struct metal_cpu *cpu, int hartid)
* @param cpu The CPU device handle
* @return The handle for the CPU interrupt controller
*/
inline struct metal_interrupt* metal_cpu_interrupt_controller(struct metal_cpu *cpu)
{ return cpu->vtable->controller_interrupt(cpu); }
__inline__ struct metal_interrupt *
metal_cpu_interrupt_controller(struct metal_cpu *cpu) {
return cpu->vtable->controller_interrupt(cpu);
}
/*!
* @brief Register an exception handler
*
* Register an exception handler for the CPU. The CPU interrupt controller must be initialized
* before this function is called.
*
* Register an exception handler for the CPU. The CPU interrupt controller must
* be initialized before this function is called.
*
* @param cpu The CPU device handle
* @param ecode The exception code to register a handler for
* @param handler Callback function for the exception handler
* @return 0 upon success
*/
inline int metal_cpu_exception_register(struct metal_cpu *cpu, int ecode, metal_exception_handler_t handler)
{ return cpu->vtable->exception_register(cpu, ecode, handler); }
__inline__ int metal_cpu_exception_register(struct metal_cpu *cpu, int ecode,
metal_exception_handler_t handler) {
return cpu->vtable->exception_register(cpu, ecode, handler);
}
/*!
* @brief Get the length of an instruction in bytes
@@ -237,8 +257,10 @@ inline int metal_cpu_exception_register(struct metal_cpu *cpu, int ecode, metal_
* @param epc The address of the instruction to measure
* @return the length of the instruction in bytes
*/
inline int metal_cpu_get_instruction_length(struct metal_cpu *cpu, uintptr_t epc)
{ return cpu->vtable->get_ilen(cpu, epc); }
__inline__ int metal_cpu_get_instruction_length(struct metal_cpu *cpu,
uintptr_t epc) {
return cpu->vtable->get_ilen(cpu, epc);
}
/*!
* @brief Get the program counter of the current exception.
@@ -249,8 +271,9 @@ inline int metal_cpu_get_instruction_length(struct metal_cpu *cpu, uintptr_t epc
* @param cpu The CPU device handle
* @return The value of the program counter at the time of the exception
*/
inline uintptr_t metal_cpu_get_exception_pc(struct metal_cpu *cpu)
{ return cpu->vtable->get_epc(cpu); }
__inline__ uintptr_t metal_cpu_get_exception_pc(struct metal_cpu *cpu) {
return cpu->vtable->get_epc(cpu);
}
/*!
* @brief Set the exception program counter
@@ -265,7 +288,20 @@ inline uintptr_t metal_cpu_get_exception_pc(struct metal_cpu *cpu)
* @param epc The address to set the exception program counter to
* @return 0 upon success
*/
inline int metal_cpu_set_exception_pc(struct metal_cpu *cpu, uintptr_t epc)
{ return cpu->vtable->set_epc(cpu, epc); }
__inline__ int metal_cpu_set_exception_pc(struct metal_cpu *cpu,
uintptr_t epc) {
return cpu->vtable->set_epc(cpu, epc);
}
/*!
* @brief Get the handle for the hart's bus error unit
*
* @param cpu The CPU device handle
* @return A pointer to the bus error unit handle
*/
__inline__ struct metal_buserror *
metal_cpu_get_buserror(struct metal_cpu *cpu) {
return cpu->vtable->get_buserror(cpu);
}
#endif
@@ -0,0 +1,32 @@
/* Copyright 2019 SiFive, Inc */
/* SPDX-License-Identifier: Apache-2.0 */
#ifndef METAL__CSR_H
#define METAL__CSR_H
#include <metal/compiler.h>
#include <stddef.h>
#include <stdint.h>
/*!
* @file csr.h
* @brief A collection of APIs for get and set CSR registers
*/
/*!
* @brief Read a given CSR register without checking validity of CSR offset
* @param crs Register label or hex value offset to read from
* @param value Variable name of uintprt_t type to get the value
*/
#define METAL_CPU_GET_CSR(reg, value) \
__asm__ volatile("csrr %0, " #reg : "=r"(value));
/*!
* @brief Write to a given CSR register without checking validity of CSR offset
* @param crs Register label or hex value offset to write to
* @param value Variable name of uintprt_t type to set the value
*/
#define METAL_CPU_SET_CSR(reg, value) \
__asm__ volatile("csrw " #reg ", %0" : : "r"(value));
#endif // METAL__CSR_H
@@ -6,8 +6,8 @@
struct __metal_driver_fixed_clock;
#include <metal/compiler.h>
#include <metal/clock.h>
#include <metal/compiler.h>
struct __metal_driver_vtable_fixed_clock {
struct __metal_clock_vtable clock;
@@ -6,8 +6,8 @@
struct __metal_driver_fixed_factor_clock;
#include <metal/compiler.h>
#include <metal/clock.h>
#include <metal/compiler.h>
struct __metal_driver_vtable_fixed_factor_clock {
struct __metal_clock_vtable clock;
@@ -21,4 +21,7 @@ struct __metal_driver_riscv_clint0 {
};
#undef __METAL_MACHINE_MACROS
int __metal_driver_riscv_clint0_command_request(
struct metal_interrupt *controller, int command, void *data);
#endif
@@ -4,148 +4,154 @@
#ifndef METAL__DRIVERS__RISCV_CPU_H
#define METAL__DRIVERS__RISCV_CPU_H
#include <stdint.h>
#include <metal/cpu.h>
#include <metal/compiler.h>
#include <metal/cpu.h>
#include <stdint.h>
#define METAL_MAX_CORES 8
#define METAL_MAX_MI 32 /* Per ISA MCause interrupts 32+ are Reserved */
#define METAL_MAX_ME 12 /* Per ISA Exception codes 12+ are Reserved */
#define METAL_DEFAULT_RTC_FREQ 32768
#define METAL_MAX_CORES 8
#define METAL_MAX_MI 32 /* Per ISA MCause interrupts 32+ are Reserved */
#define METAL_MAX_ME 12 /* Per ISA Exception codes 12+ are Reserved */
#define METAL_DEFAULT_RTC_FREQ 32768
#define METAL_DISABLE 0
#define METAL_ENABLE 1
#define METAL_DISABLE 0
#define METAL_ENABLE 1
#define METAL_ISA_A_EXTENSIONS 0x0001
#define METAL_ISA_C_EXTENSIONS 0x0004
#define METAL_ISA_D_EXTENSIONS 0x0008
#define METAL_ISA_E_EXTENSIONS 0x0010
#define METAL_ISA_F_EXTENSIONS 0x0020
#define METAL_ISA_G_EXTENSIONS 0x0040
#define METAL_ISA_I_EXTENSIONS 0x0100
#define METAL_ISA_M_EXTENSIONS 0x1000
#define METAL_ISA_N_EXTENSIONS 0x2000
#define METAL_ISA_Q_EXTENSIONS 0x10000
#define METAL_ISA_S_EXTENSIONS 0x40000
#define METAL_ISA_U_EXTENSIONS 0x100000
#define METAL_ISA_V_EXTENSIONS 0x200000
#define METAL_ISA_XL32_EXTENSIONS 0x40000000UL
#define METAL_ISA_XL64_EXTENSIONS 0x8000000000000000UL
#define METAL_ISA_A_EXTENSIONS 0x0001
#define METAL_ISA_C_EXTENSIONS 0x0004
#define METAL_ISA_D_EXTENSIONS 0x0008
#define METAL_ISA_E_EXTENSIONS 0x0010
#define METAL_ISA_F_EXTENSIONS 0x0020
#define METAL_ISA_G_EXTENSIONS 0x0040
#define METAL_ISA_I_EXTENSIONS 0x0100
#define METAL_ISA_M_EXTENSIONS 0x1000
#define METAL_ISA_N_EXTENSIONS 0x2000
#define METAL_ISA_Q_EXTENSIONS 0x10000
#define METAL_ISA_S_EXTENSIONS 0x40000
#define METAL_ISA_U_EXTENSIONS 0x100000
#define METAL_ISA_V_EXTENSIONS 0x200000
#define METAL_ISA_XL32_EXTENSIONS 0x40000000UL
#define METAL_ISA_XL64_EXTENSIONS 0x8000000000000000UL
#define METAL_ISA_XL128_EXTENSIONS 0xC000000000000000UL
#define METAL_MTVEC_DIRECT 0x00
#define METAL_MTVEC_VECTORED 0x01
#define METAL_MTVEC_CLIC 0x02
#define METAL_MTVEC_CLIC_VECTORED 0x03
#define METAL_MTVEC_CLIC_RESERVED 0x3C
#define METAL_MTVEC_MASK 0x3F
#define METAL_MTVEC_DIRECT 0x00
#define METAL_MTVEC_VECTORED 0x01
#define METAL_MTVEC_CLIC 0x02
#define METAL_MTVEC_CLIC_VECTORED 0x03
#define METAL_MTVEC_CLIC_RESERVED 0x3C
#define METAL_MTVEC_MASK 0x3F
#if __riscv_xlen == 32
#define METAL_MCAUSE_INTR 0x80000000UL
#define METAL_MCAUSE_CAUSE 0x000003FFUL
#define METAL_MCAUSE_INTR 0x80000000UL
#define METAL_MCAUSE_CAUSE 0x000003FFUL
#else
#define METAL_MCAUSE_INTR 0x8000000000000000UL
#define METAL_MCAUSE_CAUSE 0x00000000000003FFUL
#define METAL_MCAUSE_INTR 0x8000000000000000UL
#define METAL_MCAUSE_CAUSE 0x00000000000003FFUL
#endif
#define METAL_MCAUSE_MINHV 0x40000000UL
#define METAL_MCAUSE_MPP 0x30000000UL
#define METAL_MCAUSE_MPIE 0x08000000UL
#define METAL_MCAUSE_MPIL 0x00FF0000UL
#define METAL_MSTATUS_MIE 0x00000008UL
#define METAL_MSTATUS_MPIE 0x00000080UL
#define METAL_MSTATUS_MPP 0x00001800UL
#define METAL_MSTATUS_FS_INIT 0x00002000UL
#define METAL_MSTATUS_FS_CLEAN 0x00004000UL
#define METAL_MSTATUS_FS_DIRTY 0x00006000UL
#define METAL_MSTATUS_MPRV 0x00020000UL
#define METAL_MSTATUS_MXR 0x00080000UL
#define METAL_MINTSTATUS_MIL 0xFF000000UL
#define METAL_MINTSTATUS_SIL 0x0000FF00UL
#define METAL_MINTSTATUS_UIL 0x000000FFUL
#define METAL_MCAUSE_MINHV 0x40000000UL
#define METAL_MCAUSE_MPP 0x30000000UL
#define METAL_MCAUSE_MPIE 0x08000000UL
#define METAL_MCAUSE_MPIL 0x00FF0000UL
#define METAL_MSTATUS_MIE 0x00000008UL
#define METAL_MSTATUS_MPIE 0x00000080UL
#define METAL_MSTATUS_MPP 0x00001800UL
#define METAL_MSTATUS_FS_INIT 0x00002000UL
#define METAL_MSTATUS_FS_CLEAN 0x00004000UL
#define METAL_MSTATUS_FS_DIRTY 0x00006000UL
#define METAL_MSTATUS_MPRV 0x00020000UL
#define METAL_MSTATUS_MXR 0x00080000UL
#define METAL_MINTSTATUS_MIL 0xFF000000UL
#define METAL_MINTSTATUS_SIL 0x0000FF00UL
#define METAL_MINTSTATUS_UIL 0x000000FFUL
#define METAL_LOCAL_INTR(X) (16 + X)
#define METAL_MCAUSE_EVAL(cause) (cause & METAL_MCAUSE_INTR)
#define METAL_INTERRUPT(cause) (METAL_MCAUSE_EVAL(cause) ? 1 : 0)
#define METAL_EXCEPTION(cause) (METAL_MCAUSE_EVAL(cause) ? 0 : 1)
#define METAL_SW_INTR_EXCEPTION (METAL_MCAUSE_INTR + 3)
#define METAL_TMR_INTR_EXCEPTION (METAL_MCAUSE_INTR + 7)
#define METAL_EXT_INTR_EXCEPTION (METAL_MCAUSE_INTR + 11)
#define METAL_LOCAL_INTR(X) (16 + X)
#define METAL_MCAUSE_EVAL(cause) (cause & METAL_MCAUSE_INTR)
#define METAL_INTERRUPT(cause) (METAL_MCAUSE_EVAL(cause) ? 1 : 0)
#define METAL_EXCEPTION(cause) (METAL_MCAUSE_EVAL(cause) ? 0 : 1)
#define METAL_SW_INTR_EXCEPTION (METAL_MCAUSE_INTR + 3)
#define METAL_TMR_INTR_EXCEPTION (METAL_MCAUSE_INTR + 7)
#define METAL_EXT_INTR_EXCEPTION (METAL_MCAUSE_INTR + 11)
#define METAL_LOCAL_INTR_EXCEPTION(X) (METAL_MCAUSE_INTR + METAL_LOCAL_INTR(X))
#define METAL_LOCAL_INTR_RESERVE0 1
#define METAL_LOCAL_INTR_RESERVE1 2
#define METAL_LOCAL_INTR_RESERVE2 4
#define METAL_LOCAL_INTERRUPT_SW 8 /* Bit3 0x008 */
#define METAL_LOCAL_INTR_RESERVE4 16
#define METAL_LOCAL_INTR_RESERVE5 32
#define METAL_LOCAL_INTR_RESERVE6 64
#define METAL_LOCAL_INTERRUPT_TMR 128 /* Bit7 0x080 */
#define METAL_LOCAL_INTR_RESERVE8 256
#define METAL_LOCAL_INTR_RESERVE9 512
#define METAL_LOCAL_INTR_RESERVE10 1024
#define METAL_LOCAL_INTERRUPT_EXT 2048 /* Bit11 0x800 */
#define METAL_LOCAL_INTR_RESERVE0 1
#define METAL_LOCAL_INTR_RESERVE1 2
#define METAL_LOCAL_INTR_RESERVE2 4
#define METAL_LOCAL_INTERRUPT_SW 8 /* Bit3 0x008 */
#define METAL_LOCAL_INTR_RESERVE4 16
#define METAL_LOCAL_INTR_RESERVE5 32
#define METAL_LOCAL_INTR_RESERVE6 64
#define METAL_LOCAL_INTERRUPT_TMR 128 /* Bit7 0x080 */
#define METAL_LOCAL_INTR_RESERVE8 256
#define METAL_LOCAL_INTR_RESERVE9 512
#define METAL_LOCAL_INTR_RESERVE10 1024
#define METAL_LOCAL_INTERRUPT_EXT 2048 /* Bit11 0x800 */
/* Bit12 to Bit15 are Reserved */
#define METAL_LOCAL_INTERRUPT(X) (0x10000 << X) /* Bit16+ Start of Custom Local Interrupt */
#define METAL_MIE_INTERRUPT METAL_MSTATUS_MIE
#define METAL_LOCAL_INTERRUPT(X) \
(0x10000 << X) /* Bit16+ Start of Custom Local Interrupt */
#define METAL_MIE_INTERRUPT METAL_MSTATUS_MIE
#define METAL_INSN_LENGTH_MASK 3
#define METAL_INSN_NOT_COMPRESSED 3
typedef enum {
METAL_MACHINE_PRIVILEGE_MODE,
METAL_SUPERVISOR_PRIVILEGE_MODE,
METAL_USER_PRIVILEGE_MODE,
METAL_MACHINE_PRIVILEGE_MODE,
METAL_SUPERVISOR_PRIVILEGE_MODE,
METAL_USER_PRIVILEGE_MODE,
} metal_privilege_mode_e;
typedef enum {
METAL_INTERRUPT_ID_BASE,
METAL_INTERRUPT_ID_SW = (METAL_INTERRUPT_ID_BASE + 3),
METAL_INTERRUPT_ID_TMR = (METAL_INTERRUPT_ID_BASE + 7),
METAL_INTERRUPT_ID_EXT = (METAL_INTERRUPT_ID_BASE + 11),
METAL_INTERRUPT_ID_LC0 = (METAL_INTERRUPT_ID_BASE + METAL_LOCAL_INTR(0)),
METAL_INTERRUPT_ID_LC1 = (METAL_INTERRUPT_ID_BASE + METAL_LOCAL_INTR(1)),
METAL_INTERRUPT_ID_LC2 = (METAL_INTERRUPT_ID_BASE + METAL_LOCAL_INTR(2)),
METAL_INTERRUPT_ID_LC3 = (METAL_INTERRUPT_ID_BASE + METAL_LOCAL_INTR(3)),
METAL_INTERRUPT_ID_LC4 = (METAL_INTERRUPT_ID_BASE + METAL_LOCAL_INTR(4)),
METAL_INTERRUPT_ID_LC5 = (METAL_INTERRUPT_ID_BASE + METAL_LOCAL_INTR(5)),
METAL_INTERRUPT_ID_LC6 = (METAL_INTERRUPT_ID_BASE + METAL_LOCAL_INTR(6)),
METAL_INTERRUPT_ID_LC7 = (METAL_INTERRUPT_ID_BASE + METAL_LOCAL_INTR(7)),
METAL_INTERRUPT_ID_LC8 = (METAL_INTERRUPT_ID_BASE + METAL_LOCAL_INTR(8)),
METAL_INTERRUPT_ID_LC9 = (METAL_INTERRUPT_ID_BASE + METAL_LOCAL_INTR(9)),
METAL_INTERRUPT_ID_LC10 = (METAL_INTERRUPT_ID_BASE + METAL_LOCAL_INTR(10)),
METAL_INTERRUPT_ID_LC11 = (METAL_INTERRUPT_ID_BASE + METAL_LOCAL_INTR(11)),
METAL_INTERRUPT_ID_LC12 = (METAL_INTERRUPT_ID_BASE + METAL_LOCAL_INTR(12)),
METAL_INTERRUPT_ID_LC13 = (METAL_INTERRUPT_ID_BASE + METAL_LOCAL_INTR(13)),
METAL_INTERRUPT_ID_LC14 = (METAL_INTERRUPT_ID_BASE + METAL_LOCAL_INTR(14)),
METAL_INTERRUPT_ID_LC15 = (METAL_INTERRUPT_ID_BASE + METAL_LOCAL_INTR(15)),
METAL_INTERRUPT_ID_LCMX,
METAL_INTERRUPT_ID_GL0 = METAL_INTERRUPT_ID_LCMX,
METAL_INTERRUPT_ID_GLMX = (METAL_MCAUSE_CAUSE + 1),
METAL_INTERRUPT_ID_BASE,
METAL_INTERRUPT_ID_SW = (METAL_INTERRUPT_ID_BASE + 3),
METAL_INTERRUPT_ID_TMR = (METAL_INTERRUPT_ID_BASE + 7),
METAL_INTERRUPT_ID_EXT = (METAL_INTERRUPT_ID_BASE + 11),
METAL_INTERRUPT_ID_CSW = (METAL_INTERRUPT_ID_BASE + 12),
METAL_INTERRUPT_ID_LC0 = (METAL_INTERRUPT_ID_BASE + METAL_LOCAL_INTR(0)),
METAL_INTERRUPT_ID_LC1 = (METAL_INTERRUPT_ID_BASE + METAL_LOCAL_INTR(1)),
METAL_INTERRUPT_ID_LC2 = (METAL_INTERRUPT_ID_BASE + METAL_LOCAL_INTR(2)),
METAL_INTERRUPT_ID_LC3 = (METAL_INTERRUPT_ID_BASE + METAL_LOCAL_INTR(3)),
METAL_INTERRUPT_ID_LC4 = (METAL_INTERRUPT_ID_BASE + METAL_LOCAL_INTR(4)),
METAL_INTERRUPT_ID_LC5 = (METAL_INTERRUPT_ID_BASE + METAL_LOCAL_INTR(5)),
METAL_INTERRUPT_ID_LC6 = (METAL_INTERRUPT_ID_BASE + METAL_LOCAL_INTR(6)),
METAL_INTERRUPT_ID_LC7 = (METAL_INTERRUPT_ID_BASE + METAL_LOCAL_INTR(7)),
METAL_INTERRUPT_ID_LC8 = (METAL_INTERRUPT_ID_BASE + METAL_LOCAL_INTR(8)),
METAL_INTERRUPT_ID_LC9 = (METAL_INTERRUPT_ID_BASE + METAL_LOCAL_INTR(9)),
METAL_INTERRUPT_ID_LC10 = (METAL_INTERRUPT_ID_BASE + METAL_LOCAL_INTR(10)),
METAL_INTERRUPT_ID_LC11 = (METAL_INTERRUPT_ID_BASE + METAL_LOCAL_INTR(11)),
METAL_INTERRUPT_ID_LC12 = (METAL_INTERRUPT_ID_BASE + METAL_LOCAL_INTR(12)),
METAL_INTERRUPT_ID_LC13 = (METAL_INTERRUPT_ID_BASE + METAL_LOCAL_INTR(13)),
METAL_INTERRUPT_ID_LC14 = (METAL_INTERRUPT_ID_BASE + METAL_LOCAL_INTR(14)),
METAL_INTERRUPT_ID_LC15 = (METAL_INTERRUPT_ID_BASE + METAL_LOCAL_INTR(15)),
METAL_INTERRUPT_ID_LCMX,
METAL_INTERRUPT_ID_GL0 = METAL_INTERRUPT_ID_LCMX,
METAL_INTERRUPT_ID_GLMX = (METAL_MCAUSE_CAUSE + 1),
METAL_INTERRUPT_ID_BEU = 128,
} metal_interrupt_id_e;
typedef enum {
METAL_IAM_EXCEPTION_CODE, /* Instruction address misaligned */
METAL_IAF_EXCEPTION_CODE, /* Instruction access faultd */
METAL_II_EXCEPTION_CODE, /* Illegal instruction */
METAL_BREAK_EXCEPTION_CODE, /* Breakpoint */
METAL_LAM_EXCEPTION_CODE, /* Load address misaligned */
METAL_LAF_EXCEPTION_CODE, /* Load access fault */
METAL_SAMOAM_EXCEPTION_CODE, /* Store/AMO address misaligned */
METAL_SAMOAF_EXCEPTION_CODE, /* Store/AMO access fault */
METAL_ECALL_U_EXCEPTION_CODE, /* Environment call from U-mode */
METAL_R9_EXCEPTION_CODE, /* Reserved */
METAL_R10_EXCEPTION_CODE, /* Reserved */
METAL_ECALL_M_EXCEPTION_CODE, /* Environment call from M-mode */
METAL_MAX_EXCEPTION_CODE,
METAL_IAM_EXCEPTION_CODE, /* Instruction address misaligned */
METAL_IAF_EXCEPTION_CODE, /* Instruction access faultd */
METAL_II_EXCEPTION_CODE, /* Illegal instruction */
METAL_BREAK_EXCEPTION_CODE, /* Breakpoint */
METAL_LAM_EXCEPTION_CODE, /* Load address misaligned */
METAL_LAF_EXCEPTION_CODE, /* Load access fault */
METAL_SAMOAM_EXCEPTION_CODE, /* Store/AMO address misaligned */
METAL_SAMOAF_EXCEPTION_CODE, /* Store/AMO access fault */
METAL_ECALL_U_EXCEPTION_CODE, /* Environment call from U-mode */
METAL_R9_EXCEPTION_CODE, /* Reserved */
METAL_R10_EXCEPTION_CODE, /* Reserved */
METAL_ECALL_M_EXCEPTION_CODE, /* Environment call from M-mode */
METAL_MAX_EXCEPTION_CODE,
} metal_exception_code_e;
typedef enum {
METAL_TIMER_MTIME_GET = 1,
METAL_SOFTWARE_IPI_CLEAR,
METAL_SOFTWARE_IPI_SET,
METAL_SOFTWARE_MSIP_GET,
METAL_MAX_INTERRUPT_GET,
METAL_INDEX_INTERRUPT_GET,
METAL_TIMER_MTIME_GET = 1,
METAL_SOFTWARE_IPI_CLEAR,
METAL_SOFTWARE_IPI_SET,
METAL_SOFTWARE_MSIP_GET,
METAL_MAX_INTERRUPT_GET,
METAL_INDEX_INTERRUPT_GET,
} metal_interrup_cmd_e;
typedef struct __metal_interrupt_data {
long long pad : 64;
metal_interrupt_handler_t handler;
metal_interrupt_handler_t handler;
void *sub_int;
void *exint_data;
} __metal_interrupt_data;
@@ -154,30 +160,15 @@ typedef struct __metal_interrupt_data {
uintptr_t __metal_myhart_id(void);
struct __metal_driver_interrupt_controller_vtable {
void (*interrupt_init)(struct metal_interrupt *controller);
int (*interrupt_register)(struct metal_interrupt *controller,
int id, metal_interrupt_handler_t isr, void *priv_data);
int (*interrupt_enable)(struct metal_interrupt *controller, int id);
int (*interrupt_disable)(struct metal_interrupt *controller, int id);
int (*command_request)(struct metal_interrupt *intr, int cmd, void *data);
};
struct __metal_driver_vtable_riscv_cpu_intc {
struct metal_interrupt_vtable controller_vtable;
struct metal_interrupt_vtable controller_vtable;
};
void __metal_interrupt_global_enable(void);
void __metal_interrupt_global_disable(void);
void __metal_controller_interrupt_vector(metal_vector_mode mode, void *vec_table);
inline int __metal_controller_interrupt_is_selective_vectored (void)
{
uintptr_t val;
asm volatile ("csrr %0, mtvec" : "=r"(val));
return ((val & METAL_MTVEC_CLIC_VECTORED) == METAL_MTVEC_CLIC);
}
metal_vector_mode __metal_controller_interrupt_vector_mode(void);
void __metal_controller_interrupt_vector(metal_vector_mode mode,
void *vec_table);
__METAL_DECLARE_VTABLE(__metal_driver_vtable_riscv_cpu_intc)
@@ -186,18 +177,20 @@ struct __metal_driver_riscv_cpu_intc {
int init_done;
uintptr_t metal_mtvec_table[METAL_MAX_MI];
__metal_interrupt_data metal_int_table[METAL_MAX_MI];
__metal_interrupt_data metal_int_beu;
metal_exception_handler_t metal_exception_table[METAL_MAX_ME];
};
/* CPU driver*/
struct __metal_driver_vtable_cpu {
struct metal_cpu_vtable cpu_vtable;
struct metal_cpu_vtable cpu_vtable;
};
__METAL_DECLARE_VTABLE(__metal_driver_vtable_cpu)
struct __metal_driver_cpu {
struct metal_cpu cpu;
unsigned int hpm_count; /* Available HPM counters per CPU */
};
#endif
@@ -7,10 +7,10 @@
#include <metal/compiler.h>
#include <metal/drivers/riscv_cpu.h>
#define METAL_PLIC_SOURCE_MASK 0x1F
#define METAL_PLIC_SOURCE_SHIFT 5
#define METAL_PLIC_SOURCE_PRIORITY_SHIFT 2
#define METAL_PLIC_SOURCE_PENDING_SHIFT 0
#define METAL_PLIC_SOURCE_MASK 0x1F
#define METAL_PLIC_SOURCE_SHIFT 5
#define METAL_PLIC_SOURCE_PRIORITY_SHIFT 2
#define METAL_PLIC_SOURCE_PENDING_SHIFT 0
struct __metal_driver_vtable_riscv_plic0 {
struct metal_interrupt_vtable plic_vtable;
@@ -0,0 +1,184 @@
/* Copyright 2020 SiFive, Inc */
/* SPDX-License-Identifier: Apache-2.0 */
#ifndef METAL__DRIVERS__SIFIVE_BUSERROR0_H
#define METAL__DRIVERS__SIFIVE_BUSERROR0_H
/*!
* @file sifive_buserror0.h
*
* @brief API for configuring the SiFive Bus Error Unit
*/
#include <metal/compiler.h>
#include <stdbool.h>
#include <stdint.h>
/*!
* @brief The set of possible events handled by a SiFive Bus Error Unit
*/
typedef enum {
/*! @brief No event or error has been detected */
METAL_BUSERROR_EVENT_NONE = 0,
/*! @brief A correctable ECC error has occurred in the I$ or ITIM */
METAL_BUSERROR_EVENT_INST_CORRECTABLE_ECC_ERROR = (1 << 2),
/*! @brief An uncorrectable ECC error has occurred in the I$ or ITIM */
METAL_BUSERROR_EVENT_INST_UNCORRECTABLE_ECC_ERROR = (1 << 3),
/*! @brief A TileLink load or store bus error has occurred */
METAL_BUSERROR_EVENT_LOAD_STORE_ERROR = (1 << 5),
/*! @brief A correctable ECC error has occurred in the D$ or DTIM */
METAL_BUSERROR_EVENT_DATA_CORRECTABLE_ECC_ERROR = (1 << 6),
/*! @brief An uncorrectable ECC error has occurred in the D$ or DTIM */
METAL_BUSERROR_EVENT_DATA_UNCORRECTABLE_ECC_ERROR = (1 << 7),
/*! @brief Used to set/clear all interrupts or query/clear all accrued
events */
METAL_BUSERROR_EVENT_ALL =
METAL_BUSERROR_EVENT_INST_CORRECTABLE_ECC_ERROR |
METAL_BUSERROR_EVENT_INST_UNCORRECTABLE_ECC_ERROR |
METAL_BUSERROR_EVENT_LOAD_STORE_ERROR |
METAL_BUSERROR_EVENT_DATA_CORRECTABLE_ECC_ERROR |
METAL_BUSERROR_EVENT_DATA_UNCORRECTABLE_ECC_ERROR,
/*! @brief A synonym of METAL_BUSERROR_EVENT_ALL */
METAL_BUSERROR_EVENT_ANY = METAL_BUSERROR_EVENT_ALL,
/*! @brief A value which is impossible for the bus error unit to report.
* Indicates an error has occurred if provided as a return value. */
METAL_BUSERROR_EVENT_INVALID = (1 << 8),
} metal_buserror_event_t;
/*!
* @brief The handle for a bus error unit
*/
struct metal_buserror {
uint8_t __no_empty_structs;
};
/*!
* @brief Enable bus error events
*
* Enabling bus error events causes them to be registered as accrued and,
* if the corresponding interrupt is inabled, trigger interrupts.
*
* @param beu The bus error unit handle
* @param events A mask of error events to enable
* @param enabled True if the mask should be enabled, false if they should be
* disabled
* @return 0 upon success
*/
int metal_buserror_set_event_enabled(struct metal_buserror *beu,
metal_buserror_event_t events,
bool enabled);
/*!
* @brief Get enabled bus error events
* @param beu The bus error unit handle
* @return A mask of all enabled events
*/
metal_buserror_event_t
metal_buserror_get_event_enabled(struct metal_buserror *beu);
/*!
* @brief Enable or disable the platform interrupt
*
* @param beu The bus error unit handle
* @param event The error event which would trigger the interrupt
* @param enabled True if the interrupt should be enabled
* @return 0 upon success
*/
int metal_buserror_set_platform_interrupt(struct metal_buserror *beu,
metal_buserror_event_t events,
bool enabled);
/*!
* @brief Enable or disable the hart-local interrupt
*
* @param beu The bus error unit handle
* @param event The error event which would trigger the interrupt
* @param enabled True if the interrupt should be enabled
* @return 0 upon success
*/
int metal_buserror_set_local_interrupt(struct metal_buserror *beu,
metal_buserror_event_t events,
bool enabled);
/*!
* @brief Get the error event which caused the most recent interrupt
*
* This method should be called from within the interrupt handler for the bus
* error unit interrupt
*
* @param beu The bus error unit handle
* @return The event which caused the interrupt
*/
metal_buserror_event_t metal_buserror_get_cause(struct metal_buserror *beu);
/*!
* @brief Clear the cause register for the bus error unit
*
* This method should be called from within the interrupt handler for the bus
* error unit to un-latch the cause register for the next event
*
* @param beu The bus error unit handle
* @return 0 upon success
*/
int metal_buserror_clear_cause(struct metal_buserror *beu);
/*!
* @brief Get the physical address of the error event
*
* This method should be called from within the interrupt handler for the bus
* error unit.
*
* @param beu The bus error unit handle
* @return The address of the error event
*/
uintptr_t metal_buserror_get_event_address(struct metal_buserror *beu);
/*!
* @brief Returns true if the event is set in the accrued register
*
* @param beu The bus error unit handle
* @param event The event to query
* @return True if the event is set in the accrued register
*/
bool metal_buserror_is_event_accrued(struct metal_buserror *beu,
metal_buserror_event_t events);
/*!
* @brief Clear the given event from the accrued register
*
* @param beu The bus error unit handle
* @param event The event to clear
* @return 0 upon success
*/
int metal_buserror_clear_event_accrued(struct metal_buserror *beu,
metal_buserror_event_t events);
/*!
* @brief get the platform-level interrupt parent of the bus error unit
*
* @param beu The bus error unit handle
* @return A pointer to the interrupt parent
*/
struct metal_interrupt *
metal_buserror_get_platform_interrupt_parent(struct metal_buserror *beu);
/*!
* @brief Get the platform-level interrupt id for the bus error unit interrupt
*
* @param beu The bus error unit handle
* @return The interrupt id
*/
int metal_buserror_get_platform_interrupt_id(struct metal_buserror *beu);
/*!
* @brief Get the hart-local interrupt id for the bus error unit interrupt
*
* @param beu The bus error unit handle
* @return The interrupt id
*/
int metal_buserror_get_local_interrupt_id(struct metal_buserror *beu);
#endif
@@ -0,0 +1,140 @@
/* Copyright 2020 SiFive, Inc */
/* SPDX-License-Identifier: Apache-2.0 */
#ifndef METAL__DRIVERS__SIFIVE_CCACHE0_H
#define METAL__DRIVERS__SIFIVE_CCACHE0_H
/*!
* @file sifive_ccache0.h
*
* @brief API for configuring the SiFive L2 cache controller
*/
#include <metal/interrupt.h>
#include <stdint.h>
/*! @brief Cache configuration data */
typedef struct {
uint32_t num_bank;
uint32_t num_ways;
uint32_t num_sets;
uint32_t block_size;
} sifive_ccache0_config;
/*! @brief Set of values for ECC error type */
typedef enum {
SIFIVE_CCACHE0_DATA = 0,
SIFIVE_CCACHE0_DIR = 1,
} sifive_ccache0_ecc_errtype_t;
/*! @brief Initialize cache controller, enables all available
* cache-ways.
* Note: If LIM is in use, corresponding cache ways are not enabled.
* @param None.
* @return 0 If no error.*/
int sifive_ccache0_init(void);
/*! @brief Get cache configuration data.
* @param config User specified data buffer.
* @return None.*/
void sifive_ccache0_get_config(sifive_ccache0_config *config);
/*! @brief Get currently active cache ways.
* @param None.
* @return Number of cache ways enabled.*/
uint32_t sifive_ccache0_get_enabled_ways(void);
/*! @brief Enable specified cache ways.
* @param ways Number of ways to be enabled.
* @return 0 If no error.*/
int sifive_ccache0_set_enabled_ways(uint32_t ways);
/*! @brief Inject ECC error into data or meta-data.
* @param bitindex Bit index to be corrupted on next cache operation.
* @param type ECC error target location.
* @return None.*/
void sifive_ccache0_inject_ecc_error(uint32_t bitindex,
sifive_ccache0_ecc_errtype_t type);
/*! @brief Flush out entire cache block containing given address.
* @param flush_addr Address for the cache block to be flushed.
* @return None.*/
void sifive_ccache0_flush(uintptr_t flush_addr);
/*! @brief Get most recently ECC corrected address.
* @param type ECC error target location.
* @return Last corrected ECC address.*/
uintptr_t sifive_ccache0_get_ecc_fix_addr(sifive_ccache0_ecc_errtype_t type);
/*! @brief Get number of times ECC errors were corrected.
* Clears related ECC interrupt signals.
* @param type ECC error target location.
* @return Corrected ECC error count.*/
uint32_t sifive_ccache0_get_ecc_fix_count(sifive_ccache0_ecc_errtype_t type);
/*! @brief Get address location of most recent uncorrected ECC error.
* @param type ECC error target location.
* @return Last uncorrected ECC address.*/
uintptr_t sifive_ccache0_get_ecc_fail_addr(sifive_ccache0_ecc_errtype_t type);
/*! @brief Get number of times ECC errors were not corrected.
* Clears related ECC interrupt signals.
* @param type ECC error target location.
* @return Uncorrected ECC error count.*/
uint32_t sifive_ccache0_get_ecc_fail_count(sifive_ccache0_ecc_errtype_t type);
/*! @brief Get currently active way enable mask value for the given master ID.
* @param master_id Cache controller master ID.
* @return Way enable mask. */
uint64_t sifive_ccache0_get_way_mask(uint32_t master_id);
/*! @brief Set way enable mask for the given master ID.
* @param master_id Cache controller master ID.
* @param waymask Specify ways to be enabled.
* @return 0 If no error.*/
int sifive_ccache0_set_way_mask(uint32_t master_id, uint64_t waymask);
/*! @brief Select cache performance events to be counted.
* @param counter Cache performance monitor counter index.
* @param mask Event selection mask.
* @return None.*/
void sifive_ccache0_set_pmevent_selector(uint32_t counter, uint64_t mask);
/*! @brief Get currently set events for the given counter index.
* @param counter Cache performance monitor counter index.
* @return Event selection mask.*/
uint64_t sifive_ccache0_get_pmevent_selector(uint32_t counter);
/*! @brief Clears specified cache performance counter.
* @param counter Cache performance monitor counter index.
* @return None.*/
void sifive_ccache0_clr_pmevent_counter(uint32_t counter);
/*! @brief Reads specified cache performance counter.
* @param counter Cache performance monitor counter index.
* @return Counter value.*/
uint64_t sifive_ccache0_get_pmevent_counter(uint32_t counter);
/*! @brief Select cache clients to be excluded from performance monitoring.
* @param mask Client disable mask.
* @return None.*/
void sifive_ccache0_set_client_filter(uint64_t mask);
/*! @brief Get currently set cache client disable mask.
* @param None.
* @return Client disable mask.*/
uint64_t sifive_ccache0_get_client_filter(void);
/*! @brief Get interrupt IDs for the cache controller.
* @param src Interrupt trigger source index.
* @return Interrupt id.*/
int sifive_ccache0_get_interrupt_id(uint32_t src);
/*! @brief Get interrupt controller of the cache.
* The interrupt controller must be initialized before any interrupts can be
* registered or enabled with it.
* @param None.
* @return Handle for the interrupt controller.*/
struct metal_interrupt *sifive_ccache0_interrupt_controller(void);
#endif
@@ -7,21 +7,21 @@
#include <metal/compiler.h>
#include <metal/drivers/riscv_cpu.h>
#define METAL_CLIC_MAX_NMBITS 2
#define METAL_CLIC_MAX_NLBITS 8
#define METAL_CLIC_MAX_NVBITS 1
#define METAL_CLIC_MAX_NMBITS 2
#define METAL_CLIC_MAX_NLBITS 8
#define METAL_CLIC_MAX_NVBITS 1
#define METAL_SIFIVE_CLIC0_CLICCFG_NMBITS_MMODE 0x00
#define METAL_SIFIVE_CLIC0_CLICCFG_NMBITS_SMODE1 0x20
#define METAL_SIFIVE_CLIC0_CLICCFG_NMBITS_SMODE2 0x40
#define METAL_SIFIVE_CLIC0_CLICCFG_NMBITS_MASK 0x60
#define METAL_SIFIVE_CLIC0_CLICCFG_NLBITS_MASK 0x1E
#define METAL_SIFIVE_CLIC0_CLICCFG_NVBIT_MASK 0x01
#define METAL_SIFIVE_CLIC0_CLICCFG_NMBITS_MMODE 0x00
#define METAL_SIFIVE_CLIC0_CLICCFG_NMBITS_SMODE1 0x20
#define METAL_SIFIVE_CLIC0_CLICCFG_NMBITS_SMODE2 0x40
#define METAL_SIFIVE_CLIC0_CLICCFG_NMBITS_MASK 0x60
#define METAL_SIFIVE_CLIC0_CLICCFG_NLBITS_MASK 0x1E
#define METAL_SIFIVE_CLIC0_CLICCFG_NVBIT_MASK 0x01
#define METAL_CLIC_ICTRL_SMODE1_MASK 0x7F /* b8 set imply M-mode */
#define METAL_CLIC_ICTRL_SMODE2_MASK 0x3F /* b8 set M-mode, b7 clear U-mode */
#define METAL_CLIC_ICTRL_SMODE1_MASK 0x7F /* b8 set imply M-mode */
#define METAL_CLIC_ICTRL_SMODE2_MASK 0x3F /* b8 set M-mode, b7 clear U-mode */
#define METAL_MAX_INTERRUPT_LEVEL ((1 << METAL_CLIC_MAX_NLBITS) - 1)
#define METAL_MAX_INTERRUPT_LEVEL ((1 << METAL_CLIC_MAX_NLBITS) - 1)
struct __metal_driver_vtable_sifive_clic0 {
struct metal_interrupt_vtable clic_vtable;
@@ -34,9 +34,15 @@ __METAL_DECLARE_VTABLE(__metal_driver_vtable_sifive_clic0)
struct __metal_driver_sifive_clic0 {
struct metal_interrupt controller;
int init_done;
metal_interrupt_handler_t metal_mtvt_table[__METAL_CLIC_SUBINTERRUPTS];
struct {
} __attribute__((aligned(64)));
metal_interrupt_vector_handler_t
metal_mtvt_table[__METAL_CLIC_SUBINTERRUPTS];
__metal_interrupt_data metal_exint_table[__METAL_CLIC_SUBINTERRUPTS];
};
#undef __METAL_MACHINE_MACROS
int __metal_driver_sifive_clic0_command_request(
struct metal_interrupt *controller, int command, void *data);
#endif
@@ -4,9 +4,9 @@
#ifndef METAL__DRIVERS__SIFIVE_FE310_G000_HFROSC_H
#define METAL__DRIVERS__SIFIVE_FE310_G000_HFROSC_H
#include <metal/drivers/sifive_fe310-g000_prci.h>
#include <metal/compiler.h>
#include <metal/clock.h>
#include <metal/compiler.h>
#include <metal/drivers/sifive_fe310-g000_prci.h>
#include <metal/io.h>
struct __metal_driver_vtable_sifive_fe310_g000_hfrosc {
@@ -0,0 +1,21 @@
/* Copyright 2019 SiFive, Inc */
/* SPDX-License-Identifier: Apache-2.0 */
#ifndef METAL__DRIVERS__SIFIVE_FE310_G000_LFROSC_H
#define METAL__DRIVERS__SIFIVE_FE310_G000_LFROSC_H
#include <metal/clock.h>
#include <metal/compiler.h>
#include <metal/io.h>
struct __metal_driver_vtable_sifive_fe310_g000_lfrosc {
struct __metal_clock_vtable clock;
};
__METAL_DECLARE_VTABLE(__metal_driver_vtable_sifive_fe310_g000_lfrosc)
struct __metal_driver_sifive_fe310_g000_lfrosc {
struct metal_clock clock;
};
#endif
@@ -10,14 +10,16 @@
struct __metal_driver_sifive_fe310_g000_prci;
struct __metal_driver_vtable_sifive_fe310_g000_prci {
long (*get_reg)(const struct __metal_driver_sifive_fe310_g000_prci *, long offset);
long (*set_reg)(const struct __metal_driver_sifive_fe310_g000_prci *, long offset, long value);
long (*get_reg)(const struct __metal_driver_sifive_fe310_g000_prci *,
long offset);
long (*set_reg)(const struct __metal_driver_sifive_fe310_g000_prci *,
long offset, long value);
};
__METAL_DECLARE_VTABLE(__metal_driver_vtable_sifive_fe310_g000_prci)
struct __metal_driver_sifive_fe310_g000_prci {
const struct __metal_driver_vtable_sifive_fe310_g000_prci *vtable;
};
#endif
@@ -1,23 +0,0 @@
/* Copyright 2018 SiFive, Inc */
/* SPDX-License-Identifier: Apache-2.0 */
#ifndef METAL__DRIVERS__SIFIVE_FU540_C000_L2_H
#define METAL__DRIVERS__SIFIVE_FU540_C000_L2_H
struct __metal_driver_sifive_fu540_c000_l2;
#include <stdint.h>
#include <metal/cache.h>
struct __metal_driver_vtable_sifive_fu540_c000_l2 {
struct __metal_cache_vtable cache;
};
__METAL_DECLARE_VTABLE(__metal_driver_vtable_sifive_fu540_c000_l2)
struct __metal_driver_sifive_fu540_c000_l2 {
struct metal_cache cache;
};
#endif
@@ -4,12 +4,12 @@
#ifndef METAL__DRIVERS__SIFIVE_GPIO_BUTTONS_H
#define METAL__DRIVERS__SIFIVE_GPIO_BUTTONS_H
#include <string.h>
#include <metal/button.h>
#include <metal/compiler.h>
#include <string.h>
struct __metal_driver_vtable_sifive_button {
struct metal_button_vtable button_vtable;
struct metal_button_vtable button_vtable;
};
__METAL_DECLARE_VTABLE(__metal_driver_vtable_sifive_button)
@@ -4,12 +4,12 @@
#ifndef METAL__DRIVERS__SIFIVE_GPIO_LEDS_H
#define METAL__DRIVERS__SIFIVE_GPIO_LEDS_H
#include <metal/compiler.h>
#include <metal/drivers/sifive_gpio0.h>
#include <metal/led.h>
#include <metal/compiler.h>
struct __metal_driver_vtable_sifive_led {
struct metal_led_vtable led_vtable;
struct metal_led_vtable led_vtable;
};
__METAL_DECLARE_VTABLE(__metal_driver_vtable_sifive_led)
@@ -4,12 +4,12 @@
#ifndef METAL__DRIVERS__SIFIVE_GPIO_SWITCHES_H
#define METAL__DRIVERS__SIFIVE_GPIO_SWITCHES_H
#include <metal/compiler.h>
#include <metal/drivers/sifive_gpio0.h>
#include <metal/switch.h>
#include <metal/compiler.h>
struct __metal_driver_vtable_sifive_switch {
struct metal_switch_vtable switch_vtable;
struct metal_switch_vtable switch_vtable;
};
__METAL_DECLARE_VTABLE(__metal_driver_vtable_sifive_switch)
@@ -11,7 +11,7 @@ struct __metal_driver_vtable_sifive_gpio0 {
const struct __metal_gpio_vtable gpio;
};
//struct __metal_driver_sifive_gpio0;
// struct __metal_driver_sifive_gpio0;
__METAL_DECLARE_VTABLE(__metal_driver_vtable_sifive_gpio0)
@@ -0,0 +1,24 @@
/* Copyright 2019 SiFive, Inc */
/* SPDX-License-Identifier: Apache-2.0 */
#ifndef METAL__DRIVERS__SIFIVE_I2C0_H
#define METAL__DRIVERS__SIFIVE_I2C0_H
#include <metal/clock.h>
#include <metal/i2c.h>
struct __metal_driver_vtable_sifive_i2c0 {
const struct metal_i2c_vtable i2c;
};
__METAL_DECLARE_VTABLE(__metal_driver_vtable_sifive_i2c0)
struct __metal_driver_sifive_i2c0 {
struct metal_i2c i2c;
unsigned int init_done;
unsigned int baud_rate;
metal_clock_callback pre_rate_change_callback;
metal_clock_callback post_rate_change_callback;
};
#endif
@@ -0,0 +1,78 @@
/* Copyright 2020 SiFive, Inc */
/* SPDX-License-Identifier: Apache-2.0 */
#ifndef METAL__DRIVERS__SIFIVE_L2PF0_H
#define METAL__DRIVERS__SIFIVE_L2PF0_H
/*!
* @file sifive_l2pf0.h
*
* @brief API for configuring the SiFive L2 prefetcher.
*/
#include <stdint.h>
/*! @brief L2 prefetcher configuration */
typedef struct {
/* Enable L2 hardware prefetcher */
uint8_t HwPrefetchEnable;
/* Only works when CrossPageEn === 0.
Cross Page optimization disable:
0 -> Entry goes into Pause state while crossing Page boundary.
Next time when the demand miss happens on the same page, it doesnt need
to train again. 1 -> The entry is invalidated in case of a cross page. */
uint8_t CrossPageOptmDisable;
/* Enable prefetches to cross pages */
uint8_t CrossPageEn;
/* Age-out mechanism enable */
uint8_t AgeOutEn;
uint32_t PrefetchDistance;
uint32_t MaxAllowedDistance;
/* Linear to exponential threshold */
uint32_t LinToExpThreshold;
/* No. of non-matching loads to edge out an entry */
uint32_t NumLdsToAgeOut;
/* Threshold no. of Fullness (L2 MSHRs used/ total available) to stop
* sending hits */
uint32_t QFullnessThreshold;
/* Threshold no. of CacheHits for evicting SPF entry */
uint32_t HitCacheThreshold;
/* Threshold no. of MSHR hits for increasing SPF distance */
uint32_t hitMSHRThreshold;
/* Size of the comparison window for address matching */
uint32_t Window;
} sifive_l2pf0_config;
/*! @brief Enable L2 hardware prefetcher unit.
* @param None.
* @return None.*/
void sifive_l2pf0_enable(void);
/*! @brief Disable L2 hardware prefetcher unit.
* @param None.
* @return None.*/
void sifive_l2pf0_disable(void);
/*! @brief Get currently active L2 prefetcher configuration.
* @param config Pointer to user specified configuration structure.
* @return None.*/
void sifive_l2pf0_get_config(sifive_l2pf0_config *config);
/*! @brief Enables fine grain access to L2 prefetcher configuration.
* @param config Pointer to user structure with values to be set.
* @return None.*/
void sifive_l2pf0_set_config(sifive_l2pf0_config *config);
#endif
@@ -18,5 +18,4 @@ struct __metal_driver_sifive_local_external_interrupts0 {
int init_done;
};
#endif
@@ -0,0 +1,29 @@
/* Copyright 2020 SiFive, Inc */
/* SPDX-License-Identifier: Apache-2.0 */
#ifndef METAL__DRIVERS__SIFIVE_PWM0_H
#define METAL__DRIVERS__SIFIVE_PWM0_H
#include <metal/clock.h>
#include <metal/pwm.h>
struct __metal_driver_vtable_sifive_pwm0 {
const struct metal_pwm_vtable pwm;
};
/* Max possible PWM channel count */
#define METAL_MAX_PWM_CHANNELS 16
__METAL_DECLARE_VTABLE(__metal_driver_vtable_sifive_pwm0)
struct __metal_driver_sifive_pwm0 {
struct metal_pwm pwm;
unsigned int max_count;
unsigned int count_val;
unsigned int freq;
unsigned int duty[METAL_MAX_PWM_CHANNELS];
metal_clock_callback pre_rate_change_callback;
metal_clock_callback post_rate_change_callback;
};
#endif
@@ -0,0 +1,26 @@
/* Copyright 2019 SiFive, Inc */
/* SPDX-License-Identifier: Apache-2.0 */
#ifndef METAL__DRIVERS__SIFIVE_RTC0_H
#define METAL__DRIVERS__SIFIVE_RTC0_H
#include <metal/compiler.h>
#include <metal/io.h>
#include <metal/clock.h>
#include <metal/interrupt.h>
#include <metal/rtc.h>
struct __metal_driver_vtable_sifive_rtc0 {
const struct metal_rtc_vtable rtc;
};
struct __metal_driver_sifive_rtc0;
__METAL_DECLARE_VTABLE(__metal_driver_vtable_sifive_rtc0)
struct __metal_driver_sifive_rtc0 {
const struct metal_rtc rtc;
};
#endif
@@ -0,0 +1,29 @@
/* Copyright 2020 SiFive, Inc */
/* SPDX-License-Identifier: Apache-2.0 */
#ifndef METAL__DRIVERS__SIFIVE_SIMUART0_H
#define METAL__DRIVERS__SIFIVE_SIMUART0_H
#include <metal/clock.h>
#include <metal/compiler.h>
#include <metal/drivers/riscv_plic0.h>
#include <metal/drivers/sifive_gpio0.h>
#include <metal/io.h>
#include <metal/uart.h>
struct __metal_driver_vtable_sifive_simuart0 {
const struct metal_uart_vtable uart;
};
struct __metal_driver_sifive_simuart0;
__METAL_DECLARE_VTABLE(__metal_driver_vtable_sifive_simuart0)
struct __metal_driver_sifive_simuart0 {
struct metal_uart uart;
unsigned long baud_rate;
metal_clock_callback pre_rate_change_callback;
metal_clock_callback post_rate_change_callback;
};
#endif
@@ -4,9 +4,9 @@
#ifndef METAL__DRIVERS__SIFIVE_SPI0_H
#define METAL__DRIVERS__SIFIVE_SPI0_H
#include <metal/drivers/sifive_gpio0.h>
#include <metal/clock.h>
#include <metal/compiler.h>
#include <metal/drivers/sifive_gpio0.h>
#include <metal/io.h>
#include <metal/spi.h>
@@ -19,6 +19,8 @@ __METAL_DECLARE_VTABLE(__metal_driver_vtable_sifive_spi0)
struct __metal_driver_sifive_spi0 {
struct metal_spi spi;
unsigned long baud_rate;
metal_clock_callback pre_rate_change_callback;
metal_clock_callback post_rate_change_callback;
};
#endif
@@ -17,5 +17,4 @@ struct __metal_driver_sifive_test0 {
struct __metal_shutdown shutdown;
};
#endif
@@ -0,0 +1,23 @@
/* Copyright 2019 SiFive, Inc */
/* SPDX-License-Identifier: Apache-2.0 */
#ifndef METAL__DRIVERS__SIFIVE_TRACE_H
#define METAL__DRIVERS__SIFIVE_TRACE_H
#include <metal/compiler.h>
#include <metal/io.h>
#include <metal/uart.h>
struct __metal_driver_vtable_sifive_trace {
const struct metal_uart_vtable uart;
};
struct __metal_driver_sifive_trace;
__METAL_DECLARE_VTABLE(__metal_driver_vtable_sifive_trace)
struct __metal_driver_sifive_trace {
struct metal_uart uart;
};
#endif /* METAL__DRIVERS__SIFIVE_TRACE_H */
@@ -4,12 +4,12 @@
#ifndef METAL__DRIVERS__SIFIVE_UART0_H
#define METAL__DRIVERS__SIFIVE_UART0_H
#include <metal/drivers/sifive_gpio0.h>
#include <metal/drivers/riscv_plic0.h>
#include <metal/clock.h>
#include <metal/compiler.h>
#include <metal/drivers/riscv_plic0.h>
#include <metal/drivers/sifive_gpio0.h>
#include <metal/io.h>
#include <metal/uart.h>
#include <metal/compiler.h>
struct __metal_driver_vtable_sifive_uart0 {
const struct metal_uart_vtable uart;
@@ -22,7 +22,8 @@ __METAL_DECLARE_VTABLE(__metal_driver_vtable_sifive_uart0)
struct __metal_driver_sifive_uart0 {
struct metal_uart uart;
unsigned long baud_rate;
metal_clock_callback pre_rate_change_callback;
metal_clock_callback post_rate_change_callback;
};
#endif
@@ -0,0 +1,26 @@
/* Copyright 2018 SiFive, Inc */
/* SPDX-License-Identifier: Apache-2.0 */
#ifndef METAL__DRIVERS__SIFIVE_WDOG0_H
#define METAL__DRIVERS__SIFIVE_WDOG0_H
#include <metal/compiler.h>
#include <metal/io.h>
#include <metal/clock.h>
#include <metal/interrupt.h>
#include <metal/watchdog.h>
struct __metal_driver_vtable_sifive_wdog0 {
const struct metal_watchdog_vtable watchdog;
};
struct __metal_driver_sifive_wdog0;
__METAL_DECLARE_VTABLE(__metal_driver_vtable_sifive_wdog0)
struct __metal_driver_sifive_wdog0 {
const struct metal_watchdog watchdog;
};
#endif
@@ -0,0 +1,48 @@
/* Copyright 2018 SiFive, Inc */
/* SPDX-License-Identifier: Apache-2.0 */
#ifndef METAL__DRIVERS__UCB_HTIF0_H
#define METAL__DRIVERS__UCB_HTIF0_H
#include <metal/compiler.h>
#include <metal/shutdown.h>
#include <metal/uart.h>
struct __metal_driver_vtable_ucb_htif0_shutdown {
const struct __metal_shutdown_vtable shutdown;
};
struct __metal_driver_vtable_ucb_htif0_uart {
const struct metal_uart_vtable uart;
};
struct __metal_driver_ucb_htif0;
void __metal_driver_ucb_htif0_exit(const struct __metal_shutdown *test,
int code) __attribute__((noreturn));
void __metal_driver_ucb_htif0_init(struct metal_uart *uart, int baud_rate);
int __metal_driver_ucb_htif0_putc(struct metal_uart *uart, int c);
int __metal_driver_ucb_htif0_getc(struct metal_uart *uart, int *c);
int __metal_driver_ucb_htif0_get_baud_rate(struct metal_uart *guart);
int __metal_driver_ucb_htif0_set_baud_rate(struct metal_uart *guart,
int baud_rate);
struct metal_interrupt *
__metal_driver_ucb_htif0_interrupt_controller(struct metal_uart *uart);
int __metal_driver_ucb_htif0_get_interrupt_id(struct metal_uart *uart);
__METAL_DECLARE_VTABLE(__metal_driver_vtable_ucb_htif0_shutdown)
__METAL_DECLARE_VTABLE(__metal_driver_vtable_ucb_htif0_uart)
struct __metal_driver_ucb_htif0_shutdown {
struct __metal_shutdown shutdown;
const struct __metal_driver_vtable_ucb_htif0_shutdown *vtable;
};
struct __metal_driver_ucb_htif0_uart {
struct metal_uart uart;
const struct __metal_driver_vtable_ucb_htif0_uart *vtable;
};
#endif
@@ -5,6 +5,7 @@
#define METAL__GPIO_H
#include <metal/compiler.h>
#include <metal/interrupt.h>
/*!
* @file gpio.h
@@ -15,20 +16,37 @@ struct metal_gpio;
struct __metal_gpio_vtable {
int (*disable_input)(struct metal_gpio *, long pins);
int (*enable_input)(struct metal_gpio *, long pins);
long (*input)(struct metal_gpio *);
long (*output)(struct metal_gpio *);
int (*disable_output)(struct metal_gpio *, long pins);
int (*enable_output)(struct metal_gpio *, long pins);
int (*output_set)(struct metal_gpio *, long value);
int (*output_clear)(struct metal_gpio *, long value);
int (*output_toggle)(struct metal_gpio *, long value);
int (*enable_io)(struct metal_gpio *, long pins, long dest);
int (*disable_io)(struct metal_gpio *, long pins);
int (*config_int)(struct metal_gpio *, long pins, int intr_type);
int (*clear_int)(struct metal_gpio *, long pins, int intr_type);
struct metal_interrupt *(*interrupt_controller)(struct metal_gpio *gpio);
int (*get_interrupt_id)(struct metal_gpio *gpio, int pin);
};
#define METAL_GPIO_INT_DISABLE 0
#define METAL_GPIO_INT_RISING 1
#define METAL_GPIO_INT_FALLING 2
#define METAL_GPIO_INT_BOTH_EDGE 3
#define METAL_GPIO_INT_LOW 4
#define METAL_GPIO_INT_HIGH 5
#define METAL_GPIO_INT_BOTH_LEVEL 6
#define METAL_GPIO_INT_MAX 7
/*!
* @struct metal_gpio
* @brief The handle for a GPIO interface
*/
struct metal_gpio {
const struct __metal_gpio_vtable *vtable;
const struct __metal_gpio_vtable *vtable;
};
/*!
@@ -36,7 +54,21 @@ struct metal_gpio {
* @param device_num The GPIO device index
* @return The GPIO device handle, or NULL if there is no device at that index
*/
struct metal_gpio *metal_gpio_get_device(int device_num);
struct metal_gpio *metal_gpio_get_device(unsigned int device_num);
/*!
* @brief enable input on a pin
* @param gpio The handle for the GPIO interface
* @param pin The pin number indexed from 0
* @return 0 if the input is successfully enabled
*/
__inline__ int metal_gpio_enable_input(struct metal_gpio *gpio, int pin) {
if (!gpio) {
return 1;
}
return gpio->vtable->enable_input(gpio, (1 << pin));
}
/*!
* @brief Disable input on a pin
@@ -44,9 +76,9 @@ struct metal_gpio *metal_gpio_get_device(int device_num);
* @param pin The pin number indexed from 0
* @return 0 if the input is successfully disabled
*/
inline int metal_gpio_disable_input(struct metal_gpio *gpio, int pin) {
if(!gpio) {
return 1;
__inline__ int metal_gpio_disable_input(struct metal_gpio *gpio, int pin) {
if (!gpio) {
return 1;
}
return gpio->vtable->disable_input(gpio, (1 << pin));
@@ -58,14 +90,28 @@ inline int metal_gpio_disable_input(struct metal_gpio *gpio, int pin) {
* @param pin The pin number indexed from 0
* @return 0 if the output is successfully enabled
*/
inline int metal_gpio_enable_output(struct metal_gpio *gpio, int pin) {
if(!gpio) {
return 1;
__inline__ int metal_gpio_enable_output(struct metal_gpio *gpio, int pin) {
if (!gpio) {
return 1;
}
return gpio->vtable->enable_output(gpio, (1 << pin));
}
/*!
* @brief Disable output on a pin
* @param gpio The handle for the GPIO interface
* @param pin The pin number indexed from 0
* @return 0 if the output is successfully disabled
*/
__inline__ int metal_gpio_disable_output(struct metal_gpio *gpio, int pin) {
if (!gpio) {
return 1;
}
return gpio->vtable->disable_output(gpio, (1 << pin));
}
/*!
* @brief Set the output value of a GPIO pin
* @param gpio The handle for the GPIO interface
@@ -73,15 +119,15 @@ inline int metal_gpio_enable_output(struct metal_gpio *gpio, int pin) {
* @param value The value to set the pin to
* @return 0 if the output is successfully set
*/
inline int metal_gpio_set_pin(struct metal_gpio *gpio, int pin, int value) {
if(!gpio) {
return 1;
__inline__ int metal_gpio_set_pin(struct metal_gpio *gpio, int pin, int value) {
if (!gpio) {
return 1;
}
if(value == 0) {
return gpio->vtable->output_clear(gpio, (1 << pin));
if (value == 0) {
return gpio->vtable->output_clear(gpio, (1 << pin));
} else {
return gpio->vtable->output_set(gpio, (1 << pin));
return gpio->vtable->output_set(gpio, (1 << pin));
}
}
@@ -91,17 +137,37 @@ inline int metal_gpio_set_pin(struct metal_gpio *gpio, int pin, int value) {
* @param pin The pin number indexed from 0
* @return The value of the GPIO pin
*/
inline int metal_gpio_get_pin(struct metal_gpio *gpio, int pin) {
if(!gpio) {
return 0;
__inline__ int metal_gpio_get_input_pin(struct metal_gpio *gpio, int pin) {
if (!gpio) {
return 0;
}
long value = gpio->vtable->input(gpio);
if (value & (1 << pin)) {
return 1;
} else {
return 0;
}
}
/*!
* @brief Get the value of the GPIO pin
* @param gpio The handle for the GPIO interface
* @param pin The pin number indexed from 0
* @return The value of the GPIO pin
*/
__inline__ int metal_gpio_get_output_pin(struct metal_gpio *gpio, int pin) {
if (!gpio) {
return 0;
}
long value = gpio->vtable->output(gpio);
if(value & (1 << pin)) {
return 1;
if (value & (1 << pin)) {
return 1;
} else {
return 0;
return 0;
}
}
@@ -111,9 +177,9 @@ inline int metal_gpio_get_pin(struct metal_gpio *gpio, int pin) {
* @param pin The pin number indexed from 0
* @return 0 if the pin is successfully cleared
*/
inline int metal_gpio_clear_pin(struct metal_gpio *gpio, int pin) {
if(!gpio) {
return 1;
__inline__ int metal_gpio_clear_pin(struct metal_gpio *gpio, int pin) {
if (!gpio) {
return 1;
}
return gpio->vtable->output_clear(gpio, (1 << pin));
@@ -125,9 +191,9 @@ inline int metal_gpio_clear_pin(struct metal_gpio *gpio, int pin) {
* @param pin The pin number indexed from 0
* @return 0 if the pin is successfully toggled
*/
inline int metal_gpio_toggle_pin(struct metal_gpio *gpio, int pin) {
if(!gpio) {
return 1;
__inline__ int metal_gpio_toggle_pin(struct metal_gpio *gpio, int pin) {
if (!gpio) {
return 1;
}
return gpio->vtable->output_toggle(gpio, (1 << pin));
@@ -140,12 +206,82 @@ inline int metal_gpio_toggle_pin(struct metal_gpio *gpio, int pin) {
* @param io_function The IO function to set
* @return 0 if the pinmux is successfully set
*/
inline int metal_gpio_enable_pinmux(struct metal_gpio *gpio, int pin, int io_function) {
if(!gpio) {
return 1;
__inline__ int metal_gpio_enable_pinmux(struct metal_gpio *gpio, int pin,
int io_function) {
if (!gpio) {
return 1;
}
return gpio->vtable->enable_io(gpio, (1 << pin), (io_function << pin));
}
/*!
* @brief Disables the pinmux for a GPIO pin
* @param gpio The handle for the GPIO interface
* @param pin The bitmask for the pin to disable pinmux on
* @return 0 if the pinmux is successfully set
*/
__inline__ int metal_gpio_disable_pinmux(struct metal_gpio *gpio, int pin) {
if (!gpio) {
return 1;
}
return gpio->vtable->disable_io(gpio, (1 << pin));
}
/*!
* @brief Config gpio interrupt type
* @param gpio The handle for the GPIO interface
* @param pin The bitmask for the pin to enable gpio interrupt
* @param intr_type The interrupt type
* @return 0 if the interrupt mode is setup properly
*/
__inline__ int metal_gpio_config_interrupt(struct metal_gpio *gpio, int pin,
int intr_type) {
if (!gpio) {
return 1;
}
return gpio->vtable->config_int(gpio, (1 << pin), intr_type);
}
/*!
* @brief Clear gpio interrupt status
* @param gpio The handle for the GPIO interface
* @param pin The bitmask for the pin to clear gpio interrupt
* @param intr_type The interrupt type to be clear
* @return 0 if the interrupt is cleared
*/
__inline__ int metal_gpio_clear_interrupt(struct metal_gpio *gpio, int pin,
int intr_type) {
if (!gpio) {
return 1;
}
return gpio->vtable->clear_int(gpio, (1 << pin), intr_type);
}
/*!
* @brief Get the interrupt controller for a gpio
*
* @param gpio The handle for the gpio
* @return A pointer to the interrupt controller responsible for handling
* gpio interrupts.
*/
__inline__ struct metal_interrupt *
metal_gpio_interrupt_controller(struct metal_gpio *gpio) {
return gpio->vtable->interrupt_controller(gpio);
}
/*!
* @brief Get the interrupt id for a gpio
*
* @param gpio The handle for the gpio
* @param pin The bitmask for the pin to get gpio interrupt id
* @return The interrupt id corresponding to a gpio.
*/
__inline__ int metal_gpio_get_interrupt_id(struct metal_gpio *gpio, int pin) {
return gpio->vtable->get_interrupt_id(gpio, pin);
}
#endif
@@ -0,0 +1,146 @@
/* Copyright 2020 SiFive, Inc */
/* SPDX-License-Identifier: Apache-2.0 */
#ifndef METAL__HPM_H
#define METAL__HPM_H
#include <metal/cpu.h>
/*! @brief Macros for valid Event IDs */
#define METAL_HPM_EVENTID_8 (1UL << 8)
#define METAL_HPM_EVENTID_9 (1UL << 9)
#define METAL_HPM_EVENTID_10 (1UL << 10)
#define METAL_HPM_EVENTID_11 (1UL << 11)
#define METAL_HPM_EVENTID_12 (1UL << 12)
#define METAL_HPM_EVENTID_13 (1UL << 13)
#define METAL_HPM_EVENTID_14 (1UL << 14)
#define METAL_HPM_EVENTID_15 (1UL << 15)
#define METAL_HPM_EVENTID_16 (1UL << 16)
#define METAL_HPM_EVENTID_17 (1UL << 17)
#define METAL_HPM_EVENTID_18 (1UL << 18)
#define METAL_HPM_EVENTID_19 (1UL << 19)
#define METAL_HPM_EVENTID_20 (1UL << 20)
#define METAL_HPM_EVENTID_21 (1UL << 21)
#define METAL_HPM_EVENTID_22 (1UL << 22)
#define METAL_HPM_EVENTID_23 (1UL << 23)
#define METAL_HPM_EVENTID_24 (1UL << 24)
#define METAL_HPM_EVENTID_25 (1UL << 25)
#define METAL_HPM_EVENTID_26 (1UL << 26)
#define METAL_HPM_EVENTID_27 (1UL << 27)
#define METAL_HPM_EVENTID_28 (1UL << 28)
#define METAL_HPM_EVENTID_29 (1UL << 29)
#define METAL_HPM_EVENTID_30 (1UL << 30)
#define METAL_HPM_EVENTID_31 (1UL << 31)
/*! @brief Macros for valid Event Class */
#define METAL_HPM_EVENTCLASS_0 (0UL)
#define METAL_HPM_EVENTCLASS_1 (1UL)
#define METAL_HPM_EVENTCLASS_2 (2UL)
#define METAL_HPM_EVENTCLASS_3 (3UL)
#define METAL_HPM_EVENTCLASS_4 (4UL)
#define METAL_HPM_EVENTCLASS_5 (5UL)
#define METAL_HPM_EVENTCLASS_6 (6UL)
#define METAL_HPM_EVENTCLASS_7 (7UL)
#define METAL_HPM_EVENTCLASS_8 (8UL)
/*! @brief Enums for available HPM counters */
typedef enum {
METAL_HPM_CYCLE = 0,
METAL_HPM_TIME = 1,
METAL_HPM_INSTRET = 2,
METAL_HPM_COUNTER_3 = 3,
METAL_HPM_COUNTER_4 = 4,
METAL_HPM_COUNTER_5 = 5,
METAL_HPM_COUNTER_6 = 6,
METAL_HPM_COUNTER_7 = 7,
METAL_HPM_COUNTER_8 = 8,
METAL_HPM_COUNTER_9 = 9,
METAL_HPM_COUNTER_10 = 10,
METAL_HPM_COUNTER_11 = 11,
METAL_HPM_COUNTER_12 = 12,
METAL_HPM_COUNTER_13 = 13,
METAL_HPM_COUNTER_14 = 14,
METAL_HPM_COUNTER_15 = 15,
METAL_HPM_COUNTER_16 = 16,
METAL_HPM_COUNTER_17 = 17,
METAL_HPM_COUNTER_18 = 18,
METAL_HPM_COUNTER_19 = 19,
METAL_HPM_COUNTER_20 = 20,
METAL_HPM_COUNTER_21 = 21,
METAL_HPM_COUNTER_22 = 22,
METAL_HPM_COUNTER_23 = 23,
METAL_HPM_COUNTER_24 = 24,
METAL_HPM_COUNTER_25 = 25,
METAL_HPM_COUNTER_26 = 26,
METAL_HPM_COUNTER_27 = 27,
METAL_HPM_COUNTER_28 = 28,
METAL_HPM_COUNTER_29 = 29,
METAL_HPM_COUNTER_30 = 30,
METAL_HPM_COUNTER_31 = 31
} metal_hpm_counter;
/*! @brief Initialize hardware performance monitor counters.
* @param cpu The CPU device handle.
* @return 0 If no error.*/
int metal_hpm_init(struct metal_cpu *cpu);
/*! @brief Disables hardware performance monitor counters.
* Note - Disabled HPM counters may reduce power consumption.
* @param cpu The CPU device handle.
* @return 0 If no error.*/
int metal_hpm_disable(struct metal_cpu *cpu);
/*! @brief Set events which will cause the specified counter to increment.
* Counter will start incrementing from the moment events are set.
* @param cpu The CPU device handle.
* @param counter Hardware counter to be incremented by selected events.
* @param bitmask Bit-mask to select events for a particular counter,
* refer core reference manual for selection of events.
* Event bit mask is partitioned as follows:
* [XLEN-1:8] - Event selection mask [7:0] - Event class
* @return 0 If no error.*/
int metal_hpm_set_event(struct metal_cpu *cpu, metal_hpm_counter counter,
unsigned int bitmask);
/*! @brief Get events selection mask set for specified counter.
* @param cpu The CPU device handle.
* @param counter Hardware counter.
* @return Event selection bit mask. refer core reference manual for details.*/
unsigned int metal_hpm_get_event(struct metal_cpu *cpu,
metal_hpm_counter counter);
/*! @brief Clear event selector bits as per specified bit-mask.
* @param cpu The CPU device handle.
* @param counter Hardware counter.
* @return 0 If no error.*/
int metal_hpm_clr_event(struct metal_cpu *cpu, metal_hpm_counter counter,
unsigned int bitmask);
/*! @brief Enable counter access to next lower privilege mode.
* @param cpu The CPU device handle.
* @param counter Hardware counter.
* @return 0 If no error.*/
int metal_hpm_enable_access(struct metal_cpu *cpu, metal_hpm_counter counter);
/*! @brief Disable counter access to next lower privilege mode.
* @param cpu The CPU device handle.
* @param counter Hardware counter.
* @return 0 If no error.*/
int metal_hpm_disable_access(struct metal_cpu *cpu, metal_hpm_counter counter);
/*! @brief Reads current value of specified hardware counter.
* Note: 'mtime' register is memory mapped into CLINT block.
* Use CLINT APIs to access this register.
* @param cpu The CPU device handle.
* @param counter Hardware counter.
* @return Current value of hardware counter on success, 0 on failure.*/
unsigned long long metal_hpm_read_counter(struct metal_cpu *cpu,
metal_hpm_counter counter);
/*! @brief Clears off specified counter.
* @param cpu The CPU device handle.
* @param counter Hardware counter.
* @return 0 If no error.*/
int metal_hpm_clear_counter(struct metal_cpu *cpu, metal_hpm_counter counter);
#endif
@@ -0,0 +1,112 @@
/* Copyright 2019 SiFive, Inc */
/* SPDX-License-Identifier: Apache-2.0 */
#ifndef METAL__I2C_H
#define METAL__I2C_H
/*! @brief Enums to enable/disable stop condition. */
typedef enum {
METAL_I2C_STOP_DISABLE = 0,
METAL_I2C_STOP_ENABLE = 1
} metal_i2c_stop_bit_t;
/*! @brief Enums to set up I2C device modes. */
typedef enum { METAL_I2C_SLAVE = 0, METAL_I2C_MASTER = 1 } metal_i2c_mode_t;
struct metal_i2c;
struct metal_i2c_vtable {
void (*init)(struct metal_i2c *i2c, unsigned int baud_rate,
metal_i2c_mode_t mode);
int (*write)(struct metal_i2c *i2c, unsigned int addr, unsigned int len,
unsigned char buf[], metal_i2c_stop_bit_t stop_bit);
int (*read)(struct metal_i2c *i2c, unsigned int addr, unsigned int len,
unsigned char buf[], metal_i2c_stop_bit_t stop_bit);
int (*transfer)(struct metal_i2c *i2c, unsigned int addr,
unsigned char txbuf[], unsigned int txlen,
unsigned char rxbuf[], unsigned int rxlen);
int (*get_baud_rate)(struct metal_i2c *i2c);
int (*set_baud_rate)(struct metal_i2c *i2c, unsigned int baud_rate);
};
/*! @brief A handle for a I2C device. */
struct metal_i2c {
const struct metal_i2c_vtable *vtable;
};
/*! @brief Get a handle for a I2C device.
* @param device_num The index of the desired I2C device.
* @return A handle to the I2C device, or NULL if the device does not exist.*/
struct metal_i2c *metal_i2c_get_device(unsigned int device_num);
/*! @brief Initialize a I2C device with a certain baud rate.
* @param i2c The handle for the I2C device to initialize.
* @param baud_rate The baud rate for the I2C device to operate at.
* @param mode I2C operation mode.
*/
inline void metal_i2c_init(struct metal_i2c *i2c, unsigned int baud_rate,
metal_i2c_mode_t mode) {
i2c->vtable->init(i2c, baud_rate, mode);
}
/*! @brief Perform a I2C write.
* @param i2c The handle for the I2C device to perform the write operation.
* @param addr The I2C slave address for the write operation.
* @param len The number of bytes to transfer.
* @param buf The buffer to send over the I2C bus. Must be len bytes long.
* @param stop_bit Enable / Disable STOP condition.
* @return 0 if the write succeeds.
*/
inline int metal_i2c_write(struct metal_i2c *i2c, unsigned int addr,
unsigned int len, unsigned char buf[],
metal_i2c_stop_bit_t stop_bit) {
return i2c->vtable->write(i2c, addr, len, buf, stop_bit);
}
/*! @brief Perform a I2C read.
* @param i2c The handle for the I2C device to perform the read operation.
* @param addr The I2C slave address for the read operation.
* @param len The number of bytes to transfer.
* @param buf The buffer to store data from I2C bus. Must be len bytes long.
* @param stop_bit Enable / Disable STOP condition.
* @return 0 if the read succeeds.
*/
inline int metal_i2c_read(struct metal_i2c *i2c, unsigned int addr,
unsigned int len, unsigned char buf[],
metal_i2c_stop_bit_t stop_bit) {
return i2c->vtable->read(i2c, addr, len, buf, stop_bit);
}
/*! @brief Performs back to back I2C write and read operations.
* @param i2c The handle for the I2C device to perform the transfer operation.
* @param addr The I2C slave address for the transfer operation.
* @param txbuf The data buffer to be transmitted over I2C bus.
* @param txlen The number of bytes to write over I2C.
* @param rxbuf The buffer to store data received over I2C bus.
* @param rxlen The number of bytes to read over I2C.
* @return 0 if the transfer succeeds.
*/
inline int metal_i2c_transfer(struct metal_i2c *i2c, unsigned int addr,
unsigned char txbuf[], unsigned int txlen,
unsigned char rxbuf[], unsigned int rxlen) {
return i2c->vtable->transfer(i2c, addr, txbuf, txlen, rxbuf, rxlen);
}
/*! @brief Get the current baud rate of the I2C device.
* @param i2c The handle for the I2C device.
* @return The baud rate in Hz.
*/
inline int metal_i2c_get_baud_rate(struct metal_i2c *i2c) {
return i2c->vtable->get_baud_rate(i2c);
}
/*! @brief Set the current baud rate of the I2C device.
* @param i2c The handle for the I2C device.
* @param baud_rate The desired baud rate of the I2C device.
* @return 0 If the baud rate is successfully changed.
*/
inline int metal_i2c_set_baud_rate(struct metal_i2c *i2c, int baud_rate) {
return i2c->vtable->set_baud_rate(i2c, baud_rate);
}
#endif
@@ -0,0 +1,130 @@
/* Copyright 2019 SiFive Inc. */
/* SPDX-License-Identifier: Apache-2.0 */
#ifndef METAL_INIT
#define METAL_INIT
/*!
* @file init.h
* API for Metal constructors and destructors
*/
typedef void (*metal_constructor_t)(void);
typedef void (*metal_destructor_t)(void);
#define METAL_INIT_HIGHEST_PRIORITY 0
#define METAL_INIT_DEFAULT_PRIORITY 5000
#define METAL_INIT_LOWEST_PRIORITY 9999
/*! @def METAL_CONSTRUCTOR
* @brief Define a Metal constructor
*
* Functions defined with METAL_CONSTRUCTOR will be added to the list of
* Metal constructors. By default, these functions are called before main by
* the metal_init() function.
*/
#define METAL_CONSTRUCTOR(function_name) \
METAL_CONSTRUCTOR_PRIO(function_name, METAL_INIT_DEFAULT_PRIORITY)
/*! @def METAL_CONSTRUCTOR_PRIO
* @brief Define a Metal constructor with a given priority
*
* The priority argument should be an integer between 0 and 9999, where 0
* is the highest priority (runs first) and 9999 is the lowest priority
* (runs last).
*
* Functions defined with METAL_CONSTRUCTOR_PRIO will be added to the list of
* Metal constructors. By default, these functions are called before main by
* the metal_init() function.
*/
#define METAL_CONSTRUCTOR_PRIO(function_name, priority) \
__METAL_CONSTRUCTOR_PRIO(function_name, priority)
/* We use this wrapper for METAL_CONSTRUCTOR_PRIORITY so that macros passed
* as 'priority' are expanded before being stringified by the # operator.
* If we don't do this, then
* METAL_CONSTRUCTOR(my_fn_name, METAL_INIT_DEFAULT_PRIORITY)
* results in .metal.init_array.METAL_INIT_DEFAULT_PRIORITY instead of
* .metal.init_array.5000 */
#define __METAL_CONSTRUCTOR_PRIO(function_name, priority) \
__attribute__((section(".metal.ctors"))) void function_name(void); \
__attribute__((section(".metal.init_array." #priority))) \
metal_constructor_t _##function_name##_ptr = &function_name; \
void function_name(void)
/*! @def METAL_DESTRUCTOR
* @brief Define a Metal destructor
*
* Functions defined with METAL_DESTRUCTOR will be added to the list of
* Metal destructors. By default, these functions are called on exit by
* the metal_fini() function.
*/
#define METAL_DESTRUCTOR(function_name) \
METAL_DESTRUCTOR_PRIO(function_name, METAL_INIT_DEFAULT_PRIORITY)
/*! @def METAL_DESTRUCTOR_PRIO
* @brief Define a Metal destructor with a given priority
*
* The priority argument should be an integer between 0 and 9999, where 0
* is the highest priority (runs first) and 9999 is the lowest priority
* (runs last).
*
* Functions defined with METAL_DESTRUCTOR_PRIO will be added to the list of
* Metal destructors. By default, these functions are called on exit by
* the metal_fini() function.
*/
#define METAL_DESTRUCTOR_PRIO(function_name, priority) \
__METAL_DESTRUCTOR_PRIO(function_name, priority)
#define __METAL_DESTRUCTOR_PRIO(function_name, priority) \
__attribute__((section(".metal.dtors"))) void function_name(void); \
__attribute__((section(".metal.fini_array." #priority))) \
metal_destructor_t _##function_name##_ptr = &function_name; \
void function_name(void)
/*!
* @brief Call all Metal constructors
*
* Devices supported by Metal may define Metal constructors to perform
* initialization before main. This function iterates over the constructors
* and calls them in turn.
*
* You can add your own constructors to the functions called by metal_init()
* by defining functions with the METAL_CONSTRUCTOR() macro.
*
* This function is called before main by default by metal_init_run().
*/
void metal_init(void);
/*!
* @brief Call all Metal destructors
*
* Devices supported by Metal may define Metal destructors to perform
* initialization on exit. This function iterates over the destructors
* and calls them in turn.
*
* You can add your own destructors to the functions called by metal_fini()
* by defining functions with the METAL_DESTRUCTOR() macro.
*
* This function is called on exit by default by metal_fini_run().
*/
void metal_fini(void);
/*!
* @brief Weak function to call metal_init() before main
*
* This function calls metal_init() before main by default. If you wish to
* replace or augment this call to the Metal constructors, you can redefine
* metal_init_run()
*/
void metal_init_run(void);
/*!
* @brief Weak function to call metal_fini() before main
*
* This function calls metal_fini() at exit by default. If you wish to
* replace or augment this call to the Metal destructors, you can redefine
* metal_fini_run()
*/
void metal_fini_run(void);
#endif /* METAL_INIT */

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