mirror of
https://github.com/FreeRTOS/FreeRTOS-Kernel.git
synced 2025-10-14 08:47:45 -04:00
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:
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">
|
||||
|
||||
<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-gcc-8.3.0-2019.08.0/bin" valueType="string"/>
|
||||
|
||||
<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=""${workspace_loc:/${ProjName}/FreeRTOS_Source/include}""/>
|
||||
|
||||
<listOptionValue builtIn="false" value=""${workspace_loc:/${ProjName}/full_demo/Common_Demo_Tasks/include}""/>
|
||||
|
||||
<listOptionValue builtIn="false" value=""${workspace_loc:/${ProjName}}""/>
|
||||
|
||||
<listOptionValue builtIn="false" value=""${workspace_loc:/${ProjName}/FreeRTOS_Source/portable/GCC/RISC-V}""/>
|
||||
|
||||
<listOptionValue builtIn="false" value=""${workspace_loc:/${ProjName}/FreeRTOS_Source/include}""/>
|
||||
|
||||
<listOptionValue builtIn="false" value=""${workspace_loc:/${ProjName}/freedom-metal}""/>
|
||||
|
||||
<listOptionValue builtIn="false" value=""${workspace_loc:/${ProjName}/bsp/install/include}""/>
|
||||
|
||||
</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=""${workspace_loc:/${ProjName}/FreeRTOS_Source/portable/GCC/RISC-V/chip_specific_extensions/RV32I_CLINT_no_extensions}""/>
|
||||
|
||||
<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.assembler.input.1723023894" superClass="cdt.managedbuild.tool.gnu.assembler.input"/>
|
||||
|
||||
<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=""${workspace_loc:/${ProjName}/FreeRTOS_Source/portable/GCC/RISC-V/chip_specific_extensions/RV32I_CLINT_no_extensions}""/>
|
||||
</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>
|
|
@ -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 "${INPUTS}"" prefer-non-shared="true">
|
||||
|
||||
<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 "${INPUTS}"" prefer-non-shared="true">
|
||||
<language-scope id="org.eclipse.cdt.core.gcc"/>
|
||||
|
||||
<language-scope id="org.eclipse.cdt.core.g++"/>
|
||||
|
||||
</provider>
|
||||
|
||||
</extension>
|
||||
|
||||
</configuration>
|
||||
|
||||
</project>
|
|
@ -99,4 +99,7 @@ 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 */
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
HiFive1 Rev B is a low-cost, Arduino-compatible development board featuring the Freedom E310. It’s the best way to start prototyping and developing your RISC‑V 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 {
|
||||
metal,entry = <&spi0 1 65536>;
|
||||
metal,boothart = <&L6>;
|
||||
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";
|
||||
};
|
||||
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);
|
||||
};
|
||||
|
||||
|
@ -37,7 +38,6 @@ struct metal_button {
|
|||
*/
|
||||
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
|
||||
|
|
|
@ -8,7 +8,8 @@
|
|||
* @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,11 +4,9 @@
|
|||
#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) \
|
||||
(((reg) & (mask)) / ((mask) & ~((mask) << 1)))
|
||||
|
@ -17,6 +15,9 @@
|
|||
#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);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -9,8 +9,8 @@
|
|||
#ifndef METAL__CPU_H
|
||||
#define METAL__CPU_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <metal/interrupt.h>
|
||||
#include <stdint.h>
|
||||
|
||||
struct metal_cpu;
|
||||
|
||||
|
@ -20,7 +20,7 @@ struct metal_cpu;
|
|||
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);
|
||||
|
@ -32,10 +32,12 @@ struct metal_cpu_vtable {
|
|||
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);
|
||||
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,9 +4,9 @@
|
|||
#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 */
|
||||
|
@ -83,9 +83,13 @@
|
|||
#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_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,
|
||||
|
@ -97,6 +101,7 @@ typedef enum {
|
|||
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)),
|
||||
|
@ -116,6 +121,7 @@ typedef enum {
|
|||
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 {
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
|
||||
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,6 +177,7 @@ 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];
|
||||
};
|
||||
|
||||
|
@ -198,6 +190,7 @@ __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
|
||||
|
|
|
@ -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
|
|
@ -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,9 +4,9 @@
|
|||
#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;
|
||||
|
|
|
@ -4,9 +4,9 @@
|
|||
#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;
|
||||
|
|
|
@ -4,9 +4,9 @@
|
|||
#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;
|
||||
|
|
|
@ -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 doesn’t 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,14 +16,31 @@ 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
|
||||
|
@ -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,7 +76,7 @@ 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) {
|
||||
__inline__ int metal_gpio_disable_input(struct metal_gpio *gpio, int pin) {
|
||||
if (!gpio) {
|
||||
return 1;
|
||||
}
|
||||
|
@ -58,7 +90,7 @@ 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) {
|
||||
__inline__ int metal_gpio_enable_output(struct metal_gpio *gpio, int pin) {
|
||||
if (!gpio) {
|
||||
return 1;
|
||||
}
|
||||
|
@ -66,6 +98,20 @@ inline int metal_gpio_enable_output(struct metal_gpio *gpio, int pin) {
|
|||
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,7 +119,7 @@ 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) {
|
||||
__inline__ int metal_gpio_set_pin(struct metal_gpio *gpio, int pin, int value) {
|
||||
if (!gpio) {
|
||||
return 1;
|
||||
}
|
||||
|
@ -91,7 +137,27 @@ 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) {
|
||||
__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;
|
||||
}
|
||||
|
@ -111,7 +177,7 @@ 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) {
|
||||
__inline__ int metal_gpio_clear_pin(struct metal_gpio *gpio, int pin) {
|
||||
if (!gpio) {
|
||||
return 1;
|
||||
}
|
||||
|
@ -125,7 +191,7 @@ 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) {
|
||||
__inline__ int metal_gpio_toggle_pin(struct metal_gpio *gpio, int pin) {
|
||||
if (!gpio) {
|
||||
return 1;
|
||||
}
|
||||
|
@ -140,7 +206,8 @@ 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) {
|
||||
__inline__ int metal_gpio_enable_pinmux(struct metal_gpio *gpio, int pin,
|
||||
int io_function) {
|
||||
if (!gpio) {
|
||||
return 1;
|
||||
}
|
||||
|
@ -148,4 +215,73 @@ inline int metal_gpio_enable_pinmux(struct metal_gpio *gpio, int pin, int io_fun
|
|||
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 */
|
|
@ -10,34 +10,105 @@
|
|||
|
||||
#include <stddef.h>
|
||||
|
||||
/*!
|
||||
* @brief Possible interrupt controllers
|
||||
*/
|
||||
typedef enum metal_interrupt_controller_ {
|
||||
METAL_CPU_CONTROLLER = 0,
|
||||
METAL_CLINT_CONTROLLER = 1,
|
||||
METAL_CLIC_CONTROLLER = 2,
|
||||
METAL_PLIC_CONTROLLER = 3
|
||||
} metal_intr_cntrl_type;
|
||||
|
||||
/*!
|
||||
* @brief Possible mode of interrupts to operate
|
||||
*/
|
||||
typedef enum metal_vector_mode_ {
|
||||
METAL_DIRECT_MODE = 0,
|
||||
METAL_VECTOR_MODE = 1,
|
||||
METAL_SELECTIVE_VECTOR_MODE = 2,
|
||||
METAL_HARDWARE_VECTOR_MODE = 3
|
||||
METAL_SELECTIVE_NONVECTOR_MODE = 2,
|
||||
METAL_SELECTIVE_VECTOR_MODE = 3,
|
||||
METAL_HARDWARE_VECTOR_MODE = 4
|
||||
} metal_vector_mode;
|
||||
|
||||
/*!
|
||||
* @brief Possible mode of privilege interrupts to operate
|
||||
*/
|
||||
typedef enum metal_intr_priv_mode_ {
|
||||
METAL_INTR_PRIV_M_MODE = 0,
|
||||
METAL_INTR_PRIV_MU_MODE = 1,
|
||||
METAL_INTR_PRIV_MSU_MODE = 2
|
||||
} metal_intr_priv_mode;
|
||||
|
||||
/*!
|
||||
* @brief The bitmask of hart context
|
||||
*/
|
||||
typedef struct metal_affinity_ {
|
||||
unsigned long bitmask;
|
||||
} metal_affinity;
|
||||
|
||||
#define for_each_metal_affinity(bit, metal_affinity) \
|
||||
for (bit = 0; metal_affinity.bitmask; bit++, metal_affinity.bitmask >>= 1)
|
||||
|
||||
#define metal_affinity_set_val(metal_affinity, val) \
|
||||
metal_affinity.bitmask = val;
|
||||
|
||||
#define metal_affinity_set_bit(metal_affinity, bit, val) \
|
||||
metal_affinity.bitmask |= ((val & 0x1) << bit);
|
||||
|
||||
/*!
|
||||
* @brief Function signature for interrupt callback handlers
|
||||
*/
|
||||
typedef void (*metal_interrupt_handler_t)(int, void *);
|
||||
typedef void (*metal_interrupt_vector_handler_t)(void);
|
||||
|
||||
struct metal_interrupt;
|
||||
|
||||
struct metal_interrupt_vtable {
|
||||
void (*interrupt_init)(struct metal_interrupt *controller);
|
||||
int (*interrupt_set_vector_mode)(struct metal_interrupt *controller,
|
||||
metal_vector_mode mode);
|
||||
metal_vector_mode (*interrupt_get_vector_mode)(
|
||||
struct metal_interrupt *controller);
|
||||
int (*interrupt_set_privilege)(struct metal_interrupt *controller,
|
||||
metal_intr_priv_mode priv);
|
||||
metal_intr_priv_mode (*interrupt_get_privilege)(
|
||||
struct metal_interrupt *controller);
|
||||
int (*interrupt_clear)(struct metal_interrupt *controller, int id);
|
||||
int (*interrupt_set)(struct metal_interrupt *controller, int id);
|
||||
int (*interrupt_register)(struct metal_interrupt *controller, int id,
|
||||
metal_interrupt_handler_t isr, void *priv_data);
|
||||
int (*interrupt_vector_register)(struct metal_interrupt *controller, int id,
|
||||
metal_interrupt_vector_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 (*interrupt_vector_enable)(struct metal_interrupt *controller,
|
||||
int id, metal_vector_mode mode);
|
||||
int (*interrupt_vector_enable)(struct metal_interrupt *controller, int id);
|
||||
int (*interrupt_vector_disable)(struct metal_interrupt *controller, int id);
|
||||
int (*command_request)(struct metal_interrupt *controller, int cmd, void *data);
|
||||
int (*mtimecmp_set)(struct metal_interrupt *controller, int hartid, unsigned long long time);
|
||||
unsigned int (*interrupt_get_threshold)(struct metal_interrupt *controller);
|
||||
int (*interrupt_set_threshold)(struct metal_interrupt *controller,
|
||||
unsigned int threshold);
|
||||
unsigned int (*interrupt_get_priority)(struct metal_interrupt *controller,
|
||||
int id);
|
||||
int (*interrupt_set_priority)(struct metal_interrupt *controller, int id,
|
||||
unsigned int priority);
|
||||
unsigned int (*interrupt_get_preemptive_level)(
|
||||
struct metal_interrupt *controller, int id);
|
||||
int (*interrupt_set_preemptive_level)(struct metal_interrupt *controller,
|
||||
int id, unsigned int level);
|
||||
int (*command_request)(struct metal_interrupt *controller, int cmd,
|
||||
void *data);
|
||||
int (*mtimecmp_set)(struct metal_interrupt *controller, int hartid,
|
||||
unsigned long long time);
|
||||
metal_affinity (*interrupt_affinity_enable)(
|
||||
struct metal_interrupt *controller, metal_affinity bitmask, int id);
|
||||
metal_affinity (*interrupt_affinity_disable)(
|
||||
struct metal_interrupt *controller, metal_affinity bitmask, int id);
|
||||
metal_affinity (*interrupt_affinity_set_threshold)(
|
||||
struct metal_interrupt *controller, metal_affinity bitmask,
|
||||
unsigned int threshold);
|
||||
unsigned int (*interrupt_affinity_get_threshold)(
|
||||
struct metal_interrupt *controller, int context_id);
|
||||
};
|
||||
|
||||
/*!
|
||||
|
@ -56,11 +127,104 @@ struct metal_interrupt {
|
|||
*
|
||||
* @param controller The handle for the interrupt controller
|
||||
*/
|
||||
inline void metal_interrupt_init(struct metal_interrupt *controller)
|
||||
{
|
||||
return controller->vtable->interrupt_init(controller);
|
||||
__inline__ void metal_interrupt_init(struct metal_interrupt *controller) {
|
||||
controller->vtable->interrupt_init(controller);
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Get the handle for an given interrupt controller type
|
||||
* @param cntrl The type ofinterrupt controller
|
||||
* @param id The instance of the interrupt controller
|
||||
* @return A handle to the interrupt controller (CLINT, CLIC, PLIC), or
|
||||
* NULL if none is found for the requested label
|
||||
*/
|
||||
struct metal_interrupt *
|
||||
metal_interrupt_get_controller(metal_intr_cntrl_type cntrl, int id);
|
||||
|
||||
/*!
|
||||
* @brief Configure vector mode for an interrupt controller
|
||||
*
|
||||
* Configure vector mode for an interrupt controller.
|
||||
* This function must be called after initialization and before
|
||||
* configuring individual interrupts, registering ISR.
|
||||
*
|
||||
* @param controller The handle for the interrupt controller
|
||||
* @param mode The vector mode of the interrupt controller.
|
||||
* @return 0 upon success
|
||||
*/
|
||||
__inline__ int
|
||||
metal_interrupt_set_vector_mode(struct metal_interrupt *controller,
|
||||
metal_vector_mode mode) {
|
||||
return controller->vtable->interrupt_set_vector_mode(controller, mode);
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Get vector mode of a given an interrupt controller
|
||||
*
|
||||
* Configure vector mode for an interrupt controller.
|
||||
* This function must be called after initialization and before
|
||||
* configuring individual interrupts, registering ISR.
|
||||
*
|
||||
* @param controller The handle for the interrupt controller
|
||||
* @param mode The vector mode of the interrupt controller.
|
||||
* @return The interrupt vector mode
|
||||
*/
|
||||
__inline__ metal_vector_mode
|
||||
metal_interrupt_get_vector_mode(struct metal_interrupt *controller) {
|
||||
return controller->vtable->interrupt_get_vector_mode(controller);
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Configure privilege mode a of given interrupt controller
|
||||
*
|
||||
* Configure privilege mode for a given interrupt controller.
|
||||
* This function must be called after initialization and before
|
||||
* configuring individual interrupts, registering ISR.
|
||||
*
|
||||
* @param controller The handle for the interrupt controller
|
||||
* @param privilege The privilege mode of the interrupt controller.
|
||||
* @return 0 upon success
|
||||
*/
|
||||
__inline__ int metal_interrupt_set_privilege(struct metal_interrupt *controller,
|
||||
metal_intr_priv_mode privilege) {
|
||||
return controller->vtable->interrupt_set_privilege(controller, privilege);
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Get privilege mode a of given interrupt controller
|
||||
*
|
||||
* Get privilege mode for a given interrupt controller.
|
||||
* This function must be called after initialization and before
|
||||
* configuring individual interrupts, registering ISR.
|
||||
*
|
||||
* @param controller The handle for the interrupt controller
|
||||
* @return The interrupt privilege mode
|
||||
*/
|
||||
__inline__ metal_intr_priv_mode
|
||||
metal_interrupt_get_privilege(struct metal_interrupt *controller) {
|
||||
return controller->vtable->interrupt_get_privilege(controller);
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief clear an interrupt
|
||||
* @param controller The handle for the interrupt controller
|
||||
* @param id The interrupt ID to trigger
|
||||
* @return 0 upon success
|
||||
*/
|
||||
__inline__ int metal_interrupt_clear(struct metal_interrupt *controller,
|
||||
int id) {
|
||||
return controller->vtable->interrupt_clear(controller, id);
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Set an interrupt
|
||||
* @param controller The handle for the interrupt controller
|
||||
* @param id The interrupt ID to trigger
|
||||
* @return 0 upon success
|
||||
*/
|
||||
__inline__ int metal_interrupt_set(struct metal_interrupt *controller, int id) {
|
||||
return controller->vtable->interrupt_set(controller, id);
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Register an interrupt handler
|
||||
|
@ -70,12 +234,27 @@ inline void metal_interrupt_init(struct metal_interrupt *controller)
|
|||
* @param priv_data Private data for the interrupt handler
|
||||
* @return 0 upon success
|
||||
*/
|
||||
inline int metal_interrupt_register_handler(struct metal_interrupt *controller,
|
||||
int id,
|
||||
__inline__ int
|
||||
metal_interrupt_register_handler(struct metal_interrupt *controller, int id,
|
||||
metal_interrupt_handler_t handler,
|
||||
void *priv_data)
|
||||
{
|
||||
return controller->vtable->interrupt_register(controller, id, handler, priv_data);
|
||||
void *priv_data) {
|
||||
return controller->vtable->interrupt_register(controller, id, handler,
|
||||
priv_data);
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Register an interrupt vector handler
|
||||
* @param controller The handle for the interrupt controller
|
||||
* @param id The interrupt ID to register
|
||||
* @param handler The interrupt vector handler callback
|
||||
* @param priv_data Private data for the interrupt handler
|
||||
* @return 0 upon success
|
||||
*/
|
||||
__inline__ int metal_interrupt_register_vector_handler(
|
||||
struct metal_interrupt *controller, int id,
|
||||
metal_interrupt_vector_handler_t handler, void *priv_data) {
|
||||
return controller->vtable->interrupt_vector_register(controller, id,
|
||||
handler, priv_data);
|
||||
}
|
||||
|
||||
/*!
|
||||
|
@ -84,8 +263,8 @@ inline int metal_interrupt_register_handler(struct metal_interrupt *controller,
|
|||
* @param id The interrupt ID to enable
|
||||
* @return 0 upon success
|
||||
*/
|
||||
inline int metal_interrupt_enable(struct metal_interrupt *controller, int id)
|
||||
{
|
||||
__inline__ int metal_interrupt_enable(struct metal_interrupt *controller,
|
||||
int id) {
|
||||
return controller->vtable->interrupt_enable(controller, id);
|
||||
}
|
||||
|
||||
|
@ -95,22 +274,100 @@ inline int metal_interrupt_enable(struct metal_interrupt *controller, int id)
|
|||
* @param id The interrupt ID to disable
|
||||
* @return 0 upon success
|
||||
*/
|
||||
inline int metal_interrupt_disable(struct metal_interrupt *controller, int id)
|
||||
{
|
||||
__inline__ int metal_interrupt_disable(struct metal_interrupt *controller,
|
||||
int id) {
|
||||
return controller->vtable->interrupt_disable(controller, id);
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Set interrupt threshold level
|
||||
* @param controller The handle for the interrupt controller
|
||||
* @param threshold The interrupt threshold level
|
||||
* @return 0 upon success
|
||||
*/
|
||||
__inline__ int metal_interrupt_set_threshold(struct metal_interrupt *controller,
|
||||
unsigned int level) {
|
||||
return controller->vtable->interrupt_set_threshold(controller, level);
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Get an interrupt threshold level
|
||||
* @param controller The handle for the interrupt controller
|
||||
* @return The interrupt threshold level
|
||||
*/
|
||||
__inline__ unsigned int
|
||||
metal_interrupt_get_threshold(struct metal_interrupt *controller) {
|
||||
return controller->vtable->interrupt_get_threshold(controller);
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Set an interrupt priority level
|
||||
* @param controller The handle for the interrupt controller
|
||||
* @param id The interrupt ID to enable
|
||||
* @param priority The interrupt priority level
|
||||
* @return 0 upon success
|
||||
*/
|
||||
__inline__ int metal_interrupt_set_priority(struct metal_interrupt *controller,
|
||||
int id, unsigned int priority) {
|
||||
return controller->vtable->interrupt_set_priority(controller, id, priority);
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Get an interrupt priority level
|
||||
* @param controller The handle for the interrupt controller
|
||||
* @param id The interrupt ID to enable
|
||||
* @return The interrupt priority level
|
||||
*/
|
||||
__inline__ unsigned int
|
||||
metal_interrupt_get_priority(struct metal_interrupt *controller, int id) {
|
||||
return controller->vtable->interrupt_get_priority(controller, id);
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Set preemptive level and priority for a given interrupt ID
|
||||
*
|
||||
* Set the preemptive level and priority for a given interrupt ID.
|
||||
*
|
||||
* @param controller The handle for the interrupt controller
|
||||
* @param id The interrupt ID to enable
|
||||
* @param level The interrupt level and priority are encoded together
|
||||
* @return 0 upon success
|
||||
*/
|
||||
__inline__ int
|
||||
metal_interrupt_set_preemptive_level(struct metal_interrupt *controller, int id,
|
||||
unsigned int level) {
|
||||
if (controller->vtable->interrupt_set_preemptive_level)
|
||||
return controller->vtable->interrupt_set_preemptive_level(controller,
|
||||
id, level);
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Get an interrupt preemptive level
|
||||
* @param controller The handle for the interrupt controller
|
||||
* @param id The interrupt ID to enable
|
||||
* @return The interrupt level
|
||||
*/
|
||||
__inline__ unsigned int
|
||||
metal_interrupt_get_preemptive_level(struct metal_interrupt *controller,
|
||||
int id) {
|
||||
if (controller->vtable->interrupt_get_preemptive_level)
|
||||
return controller->vtable->interrupt_get_preemptive_level(controller,
|
||||
id);
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Enable an interrupt vector
|
||||
* @param controller The handle for the interrupt controller
|
||||
* @param id The interrupt ID to enable
|
||||
* @param mode The interrupt mode type to enable
|
||||
* @return 0 upon success
|
||||
*/
|
||||
inline int metal_interrupt_vector_enable(struct metal_interrupt *controller,
|
||||
int id, metal_vector_mode mode)
|
||||
{
|
||||
return controller->vtable->interrupt_vector_enable(controller, id, mode);
|
||||
__inline__ int metal_interrupt_vector_enable(struct metal_interrupt *controller,
|
||||
int id) {
|
||||
return controller->vtable->interrupt_vector_enable(controller, id);
|
||||
}
|
||||
|
||||
/*!
|
||||
|
@ -119,16 +376,215 @@ inline int metal_interrupt_vector_enable(struct metal_interrupt *controller,
|
|||
* @param id The interrupt ID to disable
|
||||
* @return 0 upon success
|
||||
*/
|
||||
inline int metal_interrupt_vector_disable(struct metal_interrupt *controller, int id)
|
||||
{
|
||||
__inline__ int
|
||||
metal_interrupt_vector_disable(struct metal_interrupt *controller, int id) {
|
||||
return controller->vtable->interrupt_vector_disable(controller, id);
|
||||
}
|
||||
|
||||
/* Utilities function to controll, manages devices via a given interrupt controller */
|
||||
inline int _metal_interrupt_command_request(struct metal_interrupt *controller,
|
||||
int cmd, void *data)
|
||||
{
|
||||
/*!
|
||||
* @brief Default interrupt vector handler, that can be overriden by user
|
||||
* @param None
|
||||
* @return None
|
||||
*/
|
||||
void __attribute__((weak, interrupt)) metal_interrupt_vector_handler(void);
|
||||
|
||||
/*!
|
||||
* @brief Metal Software interrupt vector handler, that can be overriden by user
|
||||
* @param None
|
||||
* @return None
|
||||
*/
|
||||
void __attribute__((weak, interrupt))
|
||||
metal_software_interrupt_vector_handler(void);
|
||||
|
||||
/*!
|
||||
* @brief Metal Timer interrupt vector handler, that can be overriden by user
|
||||
* @param None
|
||||
* @return None
|
||||
*/
|
||||
void __attribute__((weak, interrupt))
|
||||
metal_timer_interrupt_vector_handler(void);
|
||||
|
||||
/*!
|
||||
* @brief Metal External interrupt vector handler, that can be overriden by user
|
||||
* @param None
|
||||
* @return None
|
||||
*/
|
||||
void __attribute__((weak, interrupt))
|
||||
metal_external_interrupt_vector_handler(void);
|
||||
|
||||
/*!
|
||||
* @brief Metal Local 0 interrupt vector handler, that can be overriden by user
|
||||
* @param None
|
||||
* @return None
|
||||
*/
|
||||
void __attribute__((weak, interrupt)) metal_lc0_interrupt_vector_handler(void);
|
||||
|
||||
/*!
|
||||
* @brief Metal Local 1 interrupt vector handler, that can be overriden by user
|
||||
* @param None
|
||||
* @return None
|
||||
*/
|
||||
void __attribute__((weak, interrupt)) metal_lc1_interrupt_vector_handler(void);
|
||||
|
||||
/*!
|
||||
* @brief Metal Local 2 interrupt vector handler, that can be overriden by user
|
||||
* @param None
|
||||
* @return None
|
||||
*/
|
||||
void __attribute__((weak, interrupt)) metal_lc2_interrupt_vector_handler(void);
|
||||
|
||||
/*!
|
||||
* @brief Metal Local 3 interrupt vector handler, that can be overriden by user
|
||||
* @param None
|
||||
* @return None
|
||||
*/
|
||||
void __attribute__((weak, interrupt)) metal_lc3_interrupt_vector_handler(void);
|
||||
|
||||
/*!
|
||||
* @brief Metal Local 4 interrupt vector handler, that can be overriden by user
|
||||
* @param None
|
||||
* @return None
|
||||
*/
|
||||
void __attribute__((weak, interrupt)) metal_lc4_interrupt_vector_handler(void);
|
||||
|
||||
/*!
|
||||
* @brief Metal Local 5 interrupt vector handler, that can be overriden by user
|
||||
* @param None
|
||||
* @return None
|
||||
*/
|
||||
void __attribute__((weak, interrupt)) metal_lc5_interrupt_vector_handler(void);
|
||||
|
||||
/*!
|
||||
* @brief Metal Local 6 interrupt vector handler, that can be overriden by user
|
||||
* @param None
|
||||
* @return None
|
||||
*/
|
||||
void __attribute__((weak, interrupt)) metal_lc6_interrupt_vector_handler(void);
|
||||
|
||||
/*!
|
||||
* @brief Metal Local 7 interrupt vector handler, that can be overriden by user
|
||||
* @param None
|
||||
* @return None
|
||||
*/
|
||||
void __attribute__((weak, interrupt)) metal_lc7_interrupt_vector_handler(void);
|
||||
|
||||
/*!
|
||||
* @brief Metal Local 8 interrupt vector handler, that can be overriden by user
|
||||
* @param None
|
||||
* @return None
|
||||
*/
|
||||
void __attribute__((weak, interrupt)) metal_lc8_interrupt_vector_handler(void);
|
||||
|
||||
/*!
|
||||
* @brief Metal Local 9 interrupt vector handler, that can be overriden by user
|
||||
* @param None
|
||||
* @return None
|
||||
*/
|
||||
void __attribute__((weak, interrupt)) metal_lc9_interrupt_vector_handler(void);
|
||||
|
||||
/*!
|
||||
* @brief Metal Local 10 interrupt vector handler, that can be overriden by user
|
||||
* @param None
|
||||
* @return None
|
||||
*/
|
||||
void __attribute__((weak, interrupt)) metal_lc10_interrupt_vector_handler(void);
|
||||
|
||||
/*!
|
||||
* @brief Metal Local 11 interrupt vector handler, that can be overriden by user
|
||||
* @param None
|
||||
* @return None
|
||||
*/
|
||||
void __attribute__((weak, interrupt)) metal_lc11_interrupt_vector_handler(void);
|
||||
|
||||
/*!
|
||||
* @brief Metal Local 12 interrupt vector handler, that can be overriden by user
|
||||
* @param None
|
||||
* @return None
|
||||
*/
|
||||
void __attribute__((weak, interrupt)) metal_lc12_interrupt_vector_handler(void);
|
||||
|
||||
/*!
|
||||
* @brief Metal Local 13 interrupt vector handler, that can be overriden by user
|
||||
* @param None
|
||||
* @return None
|
||||
*/
|
||||
void __attribute__((weak, interrupt)) metal_lc13_interrupt_vector_handler(void);
|
||||
|
||||
/*!
|
||||
* @brief Metal Local 14 interrupt vector handler, that can be overriden by user
|
||||
* @param None
|
||||
* @return None
|
||||
*/
|
||||
void __attribute__((weak, interrupt)) metal_lc14_interrupt_vector_handler(void);
|
||||
|
||||
/*!
|
||||
* @brief Metal Local 15 interrupt vector handler, that can be overriden by user
|
||||
* @param None
|
||||
* @return None
|
||||
*/
|
||||
void __attribute__((weak, interrupt)) metal_lc15_interrupt_vector_handler(void);
|
||||
|
||||
/* Utilities function to controll, manages devices via a given interrupt
|
||||
* controller */
|
||||
__inline__ int
|
||||
_metal_interrupt_command_request(struct metal_interrupt *controller, int cmd,
|
||||
void *data) {
|
||||
return controller->vtable->command_request(controller, cmd, data);
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Enable an interrupt for the hart contexts
|
||||
* @param controller The handle for the interrupt controller
|
||||
* @param bitmask The bit mask of hart contexts to enable
|
||||
* @param id The interrupt ID to enable
|
||||
* @return The result of each hart context. 0 upon success at relevant bit.
|
||||
*/
|
||||
__inline__ metal_affinity
|
||||
metal_interrupt_affinity_enable(struct metal_interrupt *controller,
|
||||
metal_affinity bitmask, int id) {
|
||||
return controller->vtable->interrupt_affinity_enable(controller, bitmask,
|
||||
id);
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Disable an interrupt for the hart contexts
|
||||
* @param controller The handle for the interrupt controller
|
||||
* @param bitmask The bit mask of hart contexts to disable
|
||||
* @param id The interrupt ID to disable
|
||||
* @return The result of each hart context. 0 upon success at relevant bit.
|
||||
*/
|
||||
__inline__ metal_affinity
|
||||
metal_interrupt_affinity_disable(struct metal_interrupt *controller,
|
||||
metal_affinity bitmask, int id) {
|
||||
return controller->vtable->interrupt_affinity_disable(controller, bitmask,
|
||||
id);
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Set interrupt threshold level for the hart contexts
|
||||
* @param controller The handle for the interrupt controller
|
||||
* @param bitmask The bit mask of hart contexts to set threshold
|
||||
* @param threshold The interrupt threshold level
|
||||
* @return The result of each hart context. 0 upon success at relevant bit.
|
||||
*/
|
||||
__inline__ metal_affinity
|
||||
metal_interrupt_affinity_set_threshold(struct metal_interrupt *controller,
|
||||
metal_affinity bitmask,
|
||||
unsigned int level) {
|
||||
return controller->vtable->interrupt_affinity_set_threshold(controller,
|
||||
bitmask, level);
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Get an interrupt threshold level from the hart context
|
||||
* @param controller The handle for the interrupt controller
|
||||
* @param context_id The hart context ID to get threshold
|
||||
* @return The interrupt threshold level
|
||||
*/
|
||||
__inline__ unsigned int
|
||||
metal_interrupt_affinity_get_threshold(struct metal_interrupt *controller,
|
||||
int context_id) {
|
||||
return controller->vtable->interrupt_affinity_get_threshold(controller,
|
||||
context_id);
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -5,10 +5,11 @@
|
|||
#define METAL__IO_H
|
||||
|
||||
/* This macro enforces that the compiler will not elide the given access. */
|
||||
#define __METAL_ACCESS_ONCE(x) (*(typeof(*x) volatile *)(x))
|
||||
#define __METAL_ACCESS_ONCE(x) (*(__typeof__(*x) volatile *)(x))
|
||||
|
||||
/* Allows users to specify arbitrary fences. */
|
||||
#define __METAL_IO_FENCE(pred, succ) __asm__ volatile ("fence " #pred "," #succ ::: "memory");
|
||||
#define __METAL_IO_FENCE(pred, succ) \
|
||||
__asm__ volatile("fence " #pred "," #succ ::: "memory");
|
||||
|
||||
/* Types that explicitly describe an address as being used for memory-mapped
|
||||
* IO. These should only be accessed via __METAL_ACCESS_ONCE. */
|
||||
|
|
|
@ -9,7 +9,6 @@
|
|||
* API for manipulating ITIM allocation
|
||||
*/
|
||||
|
||||
|
||||
/*! @def METAL_PLACE_IN_ITIM
|
||||
* @brief Link a function into the ITIM
|
||||
*
|
||||
|
|
|
@ -37,7 +37,8 @@ struct metal_led* metal_led_get(char *label);
|
|||
* @brief Get a handle for a channel of an RGB LED
|
||||
* @param label The DeviceTree label for the desired LED
|
||||
* @param color The color for the LED in the DeviceTree
|
||||
* @return A handle to the LED, or NULL if none is found for the requested label and color
|
||||
* @return A handle to the LED, or NULL if none is found for the requested label
|
||||
* and color
|
||||
*/
|
||||
struct metal_led *metal_led_get_rgb(char *label, char *color);
|
||||
|
||||
|
@ -45,24 +46,32 @@ struct metal_led* metal_led_get_rgb(char *label, char *color);
|
|||
* @brief Enable an LED
|
||||
* @param led The handle for the LED
|
||||
*/
|
||||
inline void metal_led_enable(struct metal_led *led) { led->vtable->led_enable(led); }
|
||||
__inline__ void metal_led_enable(struct metal_led *led) {
|
||||
led->vtable->led_enable(led);
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Turn an LED on
|
||||
* @param led The handle for the LED
|
||||
*/
|
||||
inline void metal_led_on(struct metal_led *led) { led->vtable->led_on(led); }
|
||||
__inline__ void metal_led_on(struct metal_led *led) {
|
||||
led->vtable->led_on(led);
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Turn an LED off
|
||||
* @param led The handle for the LED
|
||||
*/
|
||||
inline void metal_led_off(struct metal_led *led) { led->vtable->led_off(led); }
|
||||
__inline__ void metal_led_off(struct metal_led *led) {
|
||||
led->vtable->led_off(led);
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Toggle the on/off state of an LED
|
||||
* @param led The handle for the LED
|
||||
*/
|
||||
inline void metal_led_toggle(struct metal_led *led) { led->vtable->led_toggle(led); }
|
||||
__inline__ void metal_led_toggle(struct metal_led *led) {
|
||||
led->vtable->led_toggle(led);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
/* Copyright 2020 SiFive, Inc */
|
||||
/* SPDX-License-Identifier: Apache-2.0 */
|
||||
|
||||
#ifndef METAL__LIM_H
|
||||
#define METAL__LIM_H
|
||||
|
||||
/*! @file lim.h
|
||||
*
|
||||
* API for manipulating LIM allocation
|
||||
*/
|
||||
|
||||
/*! @def METAL_PLACE_IN_LIM
|
||||
* @brief Link a function into the LIM
|
||||
*
|
||||
* Link a function into the LIM (Loosely Integrated
|
||||
* Memory) if the LIM is present on the target device.
|
||||
*/
|
||||
#define METAL_PLACE_IN_LIM __attribute__((section(".lim")))
|
||||
|
||||
#endif
|
|
@ -4,8 +4,9 @@
|
|||
#ifndef METAL__LOCK_H
|
||||
#define METAL__LOCK_H
|
||||
|
||||
#include <metal/memory.h>
|
||||
#include <metal/compiler.h>
|
||||
#include <metal/machine.h>
|
||||
#include <metal/memory.h>
|
||||
|
||||
/*!
|
||||
* @file lock.h
|
||||
|
@ -15,6 +16,9 @@
|
|||
/* TODO: How can we make the exception code platform-independant? */
|
||||
#define _METAL_STORE_AMO_ACCESS_FAULT 7
|
||||
|
||||
#define METAL_LOCK_BACKOFF_CYCLES 32
|
||||
#define METAL_LOCK_BACKOFF_EXPONENT 2
|
||||
|
||||
/*!
|
||||
* @def METAL_LOCK_DECLARE
|
||||
* @brief Declare a lock
|
||||
|
@ -23,8 +27,7 @@
|
|||
* is linked into a memory region which supports atomic memory operations.
|
||||
*/
|
||||
#define METAL_LOCK_DECLARE(name) \
|
||||
__attribute__((section(".data.locks"))) \
|
||||
struct metal_lock name
|
||||
__attribute__((section(".data.locks"))) struct metal_lock name
|
||||
|
||||
/*!
|
||||
* @brief A handle for a lock
|
||||
|
@ -36,15 +39,17 @@ struct metal_lock {
|
|||
/*!
|
||||
* @brief Initialize a lock
|
||||
* @param lock The handle for a lock
|
||||
* @return 0 if the lock is successfully initialized. A non-zero code indicates failure.
|
||||
* @return 0 if the lock is successfully initialized. A non-zero code indicates
|
||||
* failure.
|
||||
*
|
||||
* If the lock cannot be initialized, attempts to take or give the lock
|
||||
* will result in a Store/AMO access fault.
|
||||
*/
|
||||
inline int metal_lock_init(struct metal_lock *lock) {
|
||||
__inline__ int metal_lock_init(struct metal_lock *lock) {
|
||||
#ifdef __riscv_atomic
|
||||
/* Get a handle for the memory which holds the lock state */
|
||||
struct metal_memory *lock_mem = metal_get_memory_from_address((uintptr_t) &(lock->_state));
|
||||
struct metal_memory *lock_mem =
|
||||
metal_get_memory_from_address((uintptr_t) & (lock->_state));
|
||||
if (!lock_mem) {
|
||||
return 1;
|
||||
}
|
||||
|
@ -70,23 +75,37 @@ inline int metal_lock_init(struct metal_lock *lock) {
|
|||
* If the lock initialization failed, attempts to take a lock will result in
|
||||
* a Store/AMO access fault.
|
||||
*/
|
||||
inline int metal_lock_take(struct metal_lock *lock) {
|
||||
__inline__ int metal_lock_take(struct metal_lock *lock) {
|
||||
#ifdef __riscv_atomic
|
||||
int old = 1;
|
||||
int new = 1;
|
||||
|
||||
while(old != 0) {
|
||||
int backoff = 1;
|
||||
const int max_backoff = METAL_LOCK_BACKOFF_CYCLES * METAL_MAX_CORES;
|
||||
|
||||
while (1) {
|
||||
__asm__ volatile("amoswap.w.aq %[old], %[new], (%[state])"
|
||||
: [old] "=r"(old)
|
||||
: [new] "r"(new), [state] "r"(&(lock->_state))
|
||||
: "memory");
|
||||
|
||||
if (old == 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
for (int i = 0; i < backoff; i++) {
|
||||
__asm__ volatile("");
|
||||
}
|
||||
|
||||
if (backoff < max_backoff) {
|
||||
backoff *= METAL_LOCK_BACKOFF_EXPONENT;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
#else
|
||||
/* Store the memory address in mtval like a normal store/amo access fault */
|
||||
__asm__ ("csrw mtval, %[state]"
|
||||
:: [state] "r" (&(lock->_state)));
|
||||
__asm__("csrw mtval, %[state]" ::[state] "r"(&(lock->_state)));
|
||||
|
||||
/* Trigger a Store/AMO access fault */
|
||||
_metal_trap(_METAL_STORE_AMO_ACCESS_FAULT);
|
||||
|
@ -104,17 +123,16 @@ inline int metal_lock_take(struct metal_lock *lock) {
|
|||
* If the lock initialization failed, attempts to give a lock will result in
|
||||
* a Store/AMO access fault.
|
||||
*/
|
||||
inline int metal_lock_give(struct metal_lock *lock) {
|
||||
__inline__ int metal_lock_give(struct metal_lock *lock) {
|
||||
#ifdef __riscv_atomic
|
||||
__asm__ volatile("amoswap.w.rl x0, x0, (%[state])"
|
||||
:: [state] "r" (&(lock->_state))
|
||||
__asm__ volatile(
|
||||
"amoswap.w.rl x0, x0, (%[state])" ::[state] "r"(&(lock->_state))
|
||||
: "memory");
|
||||
|
||||
return 0;
|
||||
#else
|
||||
/* Store the memory address in mtval like a normal store/amo access fault */
|
||||
__asm__ ("csrw mtval, %[state]"
|
||||
:: [state] "r" (&(lock->_state)));
|
||||
__asm__("csrw mtval, %[state]" ::[state] "r"(&(lock->_state)));
|
||||
|
||||
/* Trigger a Store/AMO access fault */
|
||||
_metal_trap(_METAL_STORE_AMO_ACCESS_FAULT);
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -5,128 +5,181 @@
|
|||
|
||||
#ifndef ASSEMBLY
|
||||
|
||||
#ifndef SIFIVE_HIFIVE1_REVB____METAL_INLINE_H
|
||||
#define SIFIVE_HIFIVE1_REVB____METAL_INLINE_H
|
||||
#ifndef METAL_INLINE_H
|
||||
#define METAL_INLINE_H
|
||||
|
||||
#include <metal/machine.h>
|
||||
|
||||
|
||||
/* --------------------- fixed_clock ------------ */
|
||||
extern inline unsigned long __metal_driver_fixed_clock_rate(const struct metal_clock *clock);
|
||||
extern __inline__ unsigned long __metal_driver_fixed_clock_rate(const struct metal_clock *clock);
|
||||
|
||||
|
||||
/* --------------------- fixed_factor_clock ------------ */
|
||||
|
||||
|
||||
/* --------------------- sifive_clint0 ------------ */
|
||||
extern inline unsigned long __metal_driver_sifive_clint0_control_base(struct metal_interrupt *controller);
|
||||
extern inline unsigned long __metal_driver_sifive_clint0_control_size(struct metal_interrupt *controller);
|
||||
extern inline int __metal_driver_sifive_clint0_num_interrupts(struct metal_interrupt *controller);
|
||||
extern inline struct metal_interrupt * __metal_driver_sifive_clint0_interrupt_parents(struct metal_interrupt *controller, int idx);
|
||||
extern inline int __metal_driver_sifive_clint0_interrupt_lines(struct metal_interrupt *controller, int idx);
|
||||
extern __inline__ unsigned long __metal_driver_sifive_clint0_control_base(struct metal_interrupt *controller);
|
||||
extern __inline__ unsigned long __metal_driver_sifive_clint0_control_size(struct metal_interrupt *controller);
|
||||
extern __inline__ int __metal_driver_sifive_clint0_num_interrupts(struct metal_interrupt *controller);
|
||||
extern __inline__ struct metal_interrupt * __metal_driver_sifive_clint0_interrupt_parents(struct metal_interrupt *controller, int idx);
|
||||
extern __inline__ int __metal_driver_sifive_clint0_interrupt_lines(struct metal_interrupt *controller, int idx);
|
||||
|
||||
|
||||
/* --------------------- cpu ------------ */
|
||||
extern inline int __metal_driver_cpu_hartid(struct metal_cpu *cpu);
|
||||
extern inline int __metal_driver_cpu_timebase(struct metal_cpu *cpu);
|
||||
extern inline struct metal_interrupt * __metal_driver_cpu_interrupt_controller(struct metal_cpu *cpu);
|
||||
extern inline int __metal_driver_cpu_num_pmp_regions(struct metal_cpu *cpu);
|
||||
extern __inline__ int __metal_driver_cpu_hartid(struct metal_cpu *cpu);
|
||||
extern __inline__ int __metal_driver_cpu_timebase(struct metal_cpu *cpu);
|
||||
extern __inline__ struct metal_interrupt * __metal_driver_cpu_interrupt_controller(struct metal_cpu *cpu);
|
||||
extern __inline__ int __metal_driver_cpu_num_pmp_regions(struct metal_cpu *cpu);
|
||||
extern __inline__ struct metal_buserror * __metal_driver_cpu_buserror(struct metal_cpu *cpu);
|
||||
|
||||
|
||||
/* --------------------- sifive_plic0 ------------ */
|
||||
extern inline unsigned long __metal_driver_sifive_plic0_control_base(struct metal_interrupt *controller);
|
||||
extern inline unsigned long __metal_driver_sifive_plic0_control_size(struct metal_interrupt *controller);
|
||||
extern inline int __metal_driver_sifive_plic0_num_interrupts(struct metal_interrupt *controller);
|
||||
extern inline int __metal_driver_sifive_plic0_max_priority(struct metal_interrupt *controller);
|
||||
extern inline struct metal_interrupt * __metal_driver_sifive_plic0_interrupt_parents(struct metal_interrupt *controller, int idx);
|
||||
extern inline int __metal_driver_sifive_plic0_interrupt_lines(struct metal_interrupt *controller, int idx);
|
||||
extern __inline__ unsigned long __metal_driver_sifive_plic0_control_base(struct metal_interrupt *controller);
|
||||
extern __inline__ unsigned long __metal_driver_sifive_plic0_control_size(struct metal_interrupt *controller);
|
||||
extern __inline__ int __metal_driver_sifive_plic0_num_interrupts(struct metal_interrupt *controller);
|
||||
extern __inline__ int __metal_driver_sifive_plic0_max_priority(struct metal_interrupt *controller);
|
||||
extern __inline__ struct metal_interrupt * __metal_driver_sifive_plic0_interrupt_parents(struct metal_interrupt *controller, int idx);
|
||||
extern __inline__ int __metal_driver_sifive_plic0_interrupt_lines(struct metal_interrupt *controller, int idx);
|
||||
extern __inline__ int __metal_driver_sifive_plic0_context_ids(int hartid);
|
||||
|
||||
|
||||
/* --------------------- sifive_buserror0 ------------ */
|
||||
|
||||
|
||||
/* --------------------- sifive_clic0 ------------ */
|
||||
|
||||
|
||||
/* --------------------- sifive_local_external_interrupts0 ------------ */
|
||||
extern inline struct metal_interrupt * __metal_driver_sifive_local_external_interrupts0_interrupt_parent(struct metal_interrupt *controller);
|
||||
extern inline int __metal_driver_sifive_local_external_interrupts0_num_interrupts(struct metal_interrupt *controller);
|
||||
extern inline int __metal_driver_sifive_local_external_interrupts0_interrupt_lines(struct metal_interrupt *controller, int idx);
|
||||
|
||||
|
||||
/* --------------------- sifive_global_external_interrupts0 ------------ */
|
||||
|
||||
|
||||
/* --------------------- sifive_gpio0 ------------ */
|
||||
extern inline unsigned long __metal_driver_sifive_gpio0_base(struct metal_gpio *gpio);
|
||||
extern inline unsigned long __metal_driver_sifive_gpio0_size(struct metal_gpio *gpio);
|
||||
extern inline int __metal_driver_sifive_gpio0_num_interrupts(struct metal_gpio *gpio);
|
||||
extern inline struct metal_interrupt * __metal_driver_sifive_gpio0_interrupt_parent(struct metal_gpio *gpio);
|
||||
extern inline int __metal_driver_sifive_gpio0_interrupt_lines(struct metal_gpio *gpio, int idx);
|
||||
extern __inline__ unsigned long __metal_driver_sifive_gpio0_base(struct metal_gpio *gpio);
|
||||
extern __inline__ unsigned long __metal_driver_sifive_gpio0_size(struct metal_gpio *gpio);
|
||||
extern __inline__ int __metal_driver_sifive_gpio0_num_interrupts(struct metal_gpio *gpio);
|
||||
extern __inline__ struct metal_interrupt * __metal_driver_sifive_gpio0_interrupt_parent(struct metal_gpio *gpio);
|
||||
extern __inline__ int __metal_driver_sifive_gpio0_interrupt_lines(struct metal_gpio *gpio, int idx);
|
||||
|
||||
|
||||
/* --------------------- sifive_gpio_button ------------ */
|
||||
|
||||
|
||||
/* --------------------- sifive_gpio_led ------------ */
|
||||
extern inline struct metal_gpio * __metal_driver_sifive_gpio_led_gpio(struct metal_led *led);
|
||||
extern inline int __metal_driver_sifive_gpio_led_pin(struct metal_led *led);
|
||||
extern inline char * __metal_driver_sifive_gpio_led_label(struct metal_led *led);
|
||||
extern __inline__ struct metal_gpio * __metal_driver_sifive_gpio_led_gpio(struct metal_led *led);
|
||||
extern __inline__ int __metal_driver_sifive_gpio_led_pin(struct metal_led *led);
|
||||
extern __inline__ char * __metal_driver_sifive_gpio_led_label(struct metal_led *led);
|
||||
|
||||
|
||||
/* --------------------- sifive_gpio_switch ------------ */
|
||||
|
||||
|
||||
/* --------------------- sifive_i2c0 ------------ */
|
||||
extern __inline__ unsigned long __metal_driver_sifive_i2c0_control_base(struct metal_i2c *i2c);
|
||||
extern __inline__ unsigned long __metal_driver_sifive_i2c0_control_size(struct metal_i2c *i2c);
|
||||
extern __inline__ int __metal_driver_sifive_i2c0_num_interrupts(struct metal_i2c *i2c);
|
||||
extern __inline__ struct metal_interrupt * __metal_driver_sifive_i2c0_interrupt_parent(struct metal_i2c *i2c);
|
||||
extern __inline__ int __metal_driver_sifive_i2c0_interrupt_line(struct metal_i2c *i2c);
|
||||
extern __inline__ struct metal_clock * __metal_driver_sifive_i2c0_clock(struct metal_i2c *i2c);
|
||||
extern __inline__ struct __metal_driver_sifive_gpio0 * __metal_driver_sifive_i2c0_pinmux(struct metal_i2c *i2c);
|
||||
extern __inline__ unsigned long __metal_driver_sifive_i2c0_pinmux_output_selector(struct metal_i2c *i2c);
|
||||
extern __inline__ unsigned long __metal_driver_sifive_i2c0_pinmux_source_selector(struct metal_i2c *i2c);
|
||||
|
||||
|
||||
/* --------------------- sifive_pwm0 ------------ */
|
||||
extern __inline__ unsigned long __metal_driver_sifive_pwm0_control_base(struct metal_pwm *pwm);
|
||||
extern __inline__ unsigned long __metal_driver_sifive_pwm0_control_size(struct metal_pwm *pwm);
|
||||
extern __inline__ int __metal_driver_sifive_pwm0_num_interrupts(struct metal_pwm *pwm);
|
||||
extern __inline__ struct metal_interrupt * __metal_driver_sifive_pwm0_interrupt_parent(struct metal_pwm *pwm);
|
||||
extern __inline__ int __metal_driver_sifive_pwm0_interrupt_lines(struct metal_pwm *pwm, int idx);
|
||||
extern __inline__ struct metal_clock * __metal_driver_sifive_pwm0_clock(struct metal_pwm *pwm);
|
||||
extern __inline__ struct __metal_driver_sifive_gpio0 * __metal_driver_sifive_pwm0_pinmux(struct metal_pwm *pwm);
|
||||
extern __inline__ unsigned long __metal_driver_sifive_pwm0_pinmux_output_selector(struct metal_pwm *pwm);
|
||||
extern __inline__ unsigned long __metal_driver_sifive_pwm0_pinmux_source_selector(struct metal_pwm *pwm);
|
||||
extern __inline__ int __metal_driver_sifive_pwm0_compare_width(struct metal_pwm *pwm);
|
||||
extern __inline__ int __metal_driver_sifive_pwm0_comparator_count(struct metal_pwm *pwm);
|
||||
|
||||
|
||||
/* --------------------- sifive_rtc0 ------------ */
|
||||
extern __inline__ unsigned long __metal_driver_sifive_rtc0_control_base(const struct metal_rtc *const rtc);
|
||||
extern __inline__ unsigned long __metal_driver_sifive_rtc0_control_size(const struct metal_rtc *const rtc);
|
||||
extern __inline__ struct metal_interrupt * __metal_driver_sifive_rtc0_interrupt_parent(const struct metal_rtc *const rtc);
|
||||
extern __inline__ int __metal_driver_sifive_rtc0_interrupt_line(const struct metal_rtc *const rtc);
|
||||
extern __inline__ struct metal_clock * __metal_driver_sifive_rtc0_clock(const struct metal_rtc *const rtc);
|
||||
|
||||
|
||||
/* --------------------- sifive_spi0 ------------ */
|
||||
extern inline unsigned long __metal_driver_sifive_spi0_control_base(struct metal_spi *spi);
|
||||
extern inline unsigned long __metal_driver_sifive_spi0_control_size(struct metal_spi *spi);
|
||||
extern inline struct __metal_driver_sifive_gpio0 * __metal_driver_sifive_spi0_pinmux(struct metal_spi *spi);
|
||||
extern inline unsigned long __metal_driver_sifive_spi0_pinmux_output_selector(struct metal_spi *spi);
|
||||
extern inline unsigned long __metal_driver_sifive_spi0_pinmux_source_selector(struct metal_spi *spi);
|
||||
extern __inline__ unsigned long __metal_driver_sifive_spi0_control_base(struct metal_spi *spi);
|
||||
extern __inline__ unsigned long __metal_driver_sifive_spi0_control_size(struct metal_spi *spi);
|
||||
extern __inline__ struct __metal_driver_sifive_gpio0 * __metal_driver_sifive_spi0_pinmux(struct metal_spi *spi);
|
||||
extern __inline__ unsigned long __metal_driver_sifive_spi0_pinmux_output_selector(struct metal_spi *spi);
|
||||
extern __inline__ unsigned long __metal_driver_sifive_spi0_pinmux_source_selector(struct metal_spi *spi);
|
||||
|
||||
|
||||
/* --------------------- sifive_test0 ------------ */
|
||||
|
||||
|
||||
/* --------------------- sifive_trace ------------ */
|
||||
|
||||
/* --------------------- sifive_uart0 ------------ */
|
||||
extern inline unsigned long __metal_driver_sifive_uart0_control_base(struct metal_uart *uart);
|
||||
extern inline unsigned long __metal_driver_sifive_uart0_control_size(struct metal_uart *uart);
|
||||
extern inline int __metal_driver_sifive_uart0_num_interrupts(struct metal_uart *uart);
|
||||
extern inline struct metal_interrupt * __metal_driver_sifive_uart0_interrupt_parent(struct metal_uart *uart);
|
||||
extern inline int __metal_driver_sifive_uart0_interrupt_line(struct metal_uart *uart);
|
||||
extern inline struct metal_clock * __metal_driver_sifive_uart0_clock(struct metal_uart *uart);
|
||||
extern inline struct __metal_driver_sifive_gpio0 * __metal_driver_sifive_uart0_pinmux(struct metal_uart *uart);
|
||||
extern inline unsigned long __metal_driver_sifive_uart0_pinmux_output_selector(struct metal_uart *uart);
|
||||
extern inline unsigned long __metal_driver_sifive_uart0_pinmux_source_selector(struct metal_uart *uart);
|
||||
extern __inline__ unsigned long __metal_driver_sifive_uart0_control_base(struct metal_uart *uart);
|
||||
extern __inline__ unsigned long __metal_driver_sifive_uart0_control_size(struct metal_uart *uart);
|
||||
extern __inline__ int __metal_driver_sifive_uart0_num_interrupts(struct metal_uart *uart);
|
||||
extern __inline__ struct metal_interrupt * __metal_driver_sifive_uart0_interrupt_parent(struct metal_uart *uart);
|
||||
extern __inline__ int __metal_driver_sifive_uart0_interrupt_line(struct metal_uart *uart);
|
||||
extern __inline__ struct metal_clock * __metal_driver_sifive_uart0_clock(struct metal_uart *uart);
|
||||
extern __inline__ struct __metal_driver_sifive_gpio0 * __metal_driver_sifive_uart0_pinmux(struct metal_uart *uart);
|
||||
extern __inline__ unsigned long __metal_driver_sifive_uart0_pinmux_output_selector(struct metal_uart *uart);
|
||||
extern __inline__ unsigned long __metal_driver_sifive_uart0_pinmux_source_selector(struct metal_uart *uart);
|
||||
|
||||
|
||||
/* --------------------- sifive_simuart0 ------------ */
|
||||
|
||||
|
||||
/* --------------------- sifive_wdog0 ------------ */
|
||||
extern __inline__ unsigned long __metal_driver_sifive_wdog0_control_base(const struct metal_watchdog *const watchdog);
|
||||
extern __inline__ unsigned long __metal_driver_sifive_wdog0_control_size(const struct metal_watchdog *const watchdog);
|
||||
extern __inline__ struct metal_interrupt * __metal_driver_sifive_wdog0_interrupt_parent(const struct metal_watchdog *const watchdog);
|
||||
extern __inline__ int __metal_driver_sifive_wdog0_interrupt_line(const struct metal_watchdog *const watchdog);
|
||||
extern __inline__ struct metal_clock * __metal_driver_sifive_wdog0_clock(const struct metal_watchdog *const watchdog);
|
||||
|
||||
|
||||
/* --------------------- sifive_fe310_g000_hfrosc ------------ */
|
||||
extern inline struct metal_clock * __metal_driver_sifive_fe310_g000_hfrosc_ref(const struct metal_clock *clock);
|
||||
extern inline struct __metal_driver_sifive_fe310_g000_prci * __metal_driver_sifive_fe310_g000_hfrosc_config_base(const struct metal_clock *clock);
|
||||
extern inline const struct __metal_driver_vtable_sifive_fe310_g000_prci * __metal_driver_sifive_fe310_g000_hfrosc_config_vtable(struct metal_clock *clock);
|
||||
extern inline long __metal_driver_sifive_fe310_g000_hfrosc_config_offset(const struct metal_clock *clock);
|
||||
extern __inline__ struct metal_clock * __metal_driver_sifive_fe310_g000_hfrosc_ref(const struct metal_clock *clock);
|
||||
extern __inline__ struct __metal_driver_sifive_fe310_g000_prci * __metal_driver_sifive_fe310_g000_hfrosc_config_base(const struct metal_clock *clock);
|
||||
extern __inline__ const struct __metal_driver_vtable_sifive_fe310_g000_prci * __metal_driver_sifive_fe310_g000_hfrosc_config_vtable(struct metal_clock *clock);
|
||||
extern __inline__ long __metal_driver_sifive_fe310_g000_hfrosc_config_offset(const struct metal_clock *clock);
|
||||
|
||||
|
||||
/* --------------------- sifive_fe310_g000_hfxosc ------------ */
|
||||
extern inline struct metal_clock * __metal_driver_sifive_fe310_g000_hfxosc_ref(const struct metal_clock *clock);
|
||||
extern inline struct __metal_driver_sifive_fe310_g000_prci * __metal_driver_sifive_fe310_g000_hfxosc_config_base(const struct metal_clock *clock);
|
||||
extern inline long __metal_driver_sifive_fe310_g000_hfxosc_config_offset(const struct metal_clock *clock);
|
||||
extern __inline__ struct metal_clock * __metal_driver_sifive_fe310_g000_hfxosc_ref(const struct metal_clock *clock);
|
||||
extern __inline__ struct __metal_driver_sifive_fe310_g000_prci * __metal_driver_sifive_fe310_g000_hfxosc_config_base(const struct metal_clock *clock);
|
||||
extern __inline__ long __metal_driver_sifive_fe310_g000_hfxosc_config_offset(const struct metal_clock *clock);
|
||||
|
||||
|
||||
/* --------------------- sifive_fe310_g000_lfrosc ------------ */
|
||||
extern __inline__ struct metal_clock * __metal_driver_sifive_fe310_g000_lfrosc_lfrosc(const struct metal_clock *clock);
|
||||
extern __inline__ struct metal_clock * __metal_driver_sifive_fe310_g000_lfrosc_psdlfaltclk(const struct metal_clock *clock);
|
||||
extern __inline__ unsigned long int __metal_driver_sifive_fe310_g000_lfrosc_config_reg(const struct metal_clock *clock);
|
||||
extern __inline__ unsigned long int __metal_driver_sifive_fe310_g000_lfrosc_mux_reg(const struct metal_clock *clock);
|
||||
|
||||
|
||||
/* --------------------- sifive_fe310_g000_pll ------------ */
|
||||
extern inline struct metal_clock * __metal_driver_sifive_fe310_g000_pll_pllsel0(const struct metal_clock *clock);
|
||||
extern inline struct metal_clock * __metal_driver_sifive_fe310_g000_pll_pllref(const struct metal_clock *clock);
|
||||
extern inline struct __metal_driver_sifive_fe310_g000_prci * __metal_driver_sifive_fe310_g000_pll_config_base( );
|
||||
extern inline long __metal_driver_sifive_fe310_g000_pll_config_offset( );
|
||||
extern inline struct __metal_driver_sifive_fe310_g000_prci * __metal_driver_sifive_fe310_g000_pll_divider_base(const struct metal_clock *clock);
|
||||
extern inline long __metal_driver_sifive_fe310_g000_pll_divider_offset(const struct metal_clock *clock);
|
||||
extern inline long __metal_driver_sifive_fe310_g000_pll_init_rate( );
|
||||
extern __inline__ struct metal_clock * __metal_driver_sifive_fe310_g000_pll_pllsel0(const struct metal_clock *clock);
|
||||
extern __inline__ struct metal_clock * __metal_driver_sifive_fe310_g000_pll_pllref(const struct metal_clock *clock);
|
||||
extern __inline__ struct __metal_driver_sifive_fe310_g000_prci * __metal_driver_sifive_fe310_g000_pll_config_base( );
|
||||
extern __inline__ long __metal_driver_sifive_fe310_g000_pll_config_offset( );
|
||||
extern __inline__ struct __metal_driver_sifive_fe310_g000_prci * __metal_driver_sifive_fe310_g000_pll_divider_base(const struct metal_clock *clock);
|
||||
extern __inline__ long __metal_driver_sifive_fe310_g000_pll_divider_offset(const struct metal_clock *clock);
|
||||
extern __inline__ long __metal_driver_sifive_fe310_g000_pll_init_rate( );
|
||||
|
||||
|
||||
/* --------------------- fe310_g000_prci ------------ */
|
||||
extern inline long __metal_driver_sifive_fe310_g000_prci_base( );
|
||||
extern inline long __metal_driver_sifive_fe310_g000_prci_size( );
|
||||
extern inline const struct __metal_driver_vtable_sifive_fe310_g000_prci * __metal_driver_sifive_fe310_g000_prci_vtable( );
|
||||
|
||||
|
||||
/* --------------------- sifive_fu540_c000_l2 ------------ */
|
||||
extern __inline__ long __metal_driver_sifive_fe310_g000_prci_base( );
|
||||
extern __inline__ long __metal_driver_sifive_fe310_g000_prci_size( );
|
||||
extern __inline__ const struct __metal_driver_vtable_sifive_fe310_g000_prci * __metal_driver_sifive_fe310_g000_prci_vtable( );
|
||||
|
||||
|
||||
/* From clock@0 */
|
||||
|
@ -144,6 +197,11 @@ struct __metal_driver_fixed_clock __metal_dt_clock_5 = {
|
|||
.clock.vtable = &__metal_driver_vtable_fixed_clock.clock,
|
||||
};
|
||||
|
||||
/* From clock@6 */
|
||||
struct __metal_driver_fixed_clock __metal_dt_clock_6 = {
|
||||
.clock.vtable = &__metal_driver_vtable_fixed_clock.clock,
|
||||
};
|
||||
|
||||
struct metal_memory __metal_dt_mem_dtim_80000000 = {
|
||||
._base_address = 2147483648UL,
|
||||
._size = 16384UL,
|
||||
|
@ -155,6 +213,17 @@ struct metal_memory __metal_dt_mem_dtim_80000000 = {
|
|||
.A = 1},
|
||||
};
|
||||
|
||||
struct metal_memory __metal_dt_mem_itim_8000000 = {
|
||||
._base_address = 134217728UL,
|
||||
._size = 8192UL,
|
||||
._attrs = {
|
||||
.R = 1,
|
||||
.W = 1,
|
||||
.X = 1,
|
||||
.C = 1,
|
||||
.A = 1},
|
||||
};
|
||||
|
||||
struct metal_memory __metal_dt_mem_spi_10014000 = {
|
||||
._base_address = 536870912UL,
|
||||
._size = 500000UL,
|
||||
|
@ -166,6 +235,24 @@ struct metal_memory __metal_dt_mem_spi_10014000 = {
|
|||
.A = 1},
|
||||
};
|
||||
|
||||
struct metal_memory __metal_dt_mem_spi_10024000 = {
|
||||
._attrs = {
|
||||
.R = 1,
|
||||
.W = 1,
|
||||
.X = 1,
|
||||
.C = 1,
|
||||
.A = 1},
|
||||
};
|
||||
|
||||
struct metal_memory __metal_dt_mem_spi_10034000 = {
|
||||
._attrs = {
|
||||
.R = 1,
|
||||
.W = 1,
|
||||
.X = 1,
|
||||
.C = 1,
|
||||
.A = 1},
|
||||
};
|
||||
|
||||
/* From clint@2000000 */
|
||||
struct __metal_driver_riscv_clint0 __metal_dt_clint_2000000 = {
|
||||
.controller.vtable = &__metal_driver_vtable_riscv_clint0.clint_vtable,
|
||||
|
@ -175,6 +262,7 @@ struct __metal_driver_riscv_clint0 __metal_dt_clint_2000000 = {
|
|||
/* From cpu@0 */
|
||||
struct __metal_driver_cpu __metal_dt_cpu_0 = {
|
||||
.cpu.vtable = &__metal_driver_vtable_cpu.cpu_vtable,
|
||||
.hpm_count = 0,
|
||||
};
|
||||
|
||||
/* From interrupt_controller */
|
||||
|
@ -189,42 +277,83 @@ struct __metal_driver_riscv_plic0 __metal_dt_interrupt_controller_c000000 = {
|
|||
.init_done = 0,
|
||||
};
|
||||
|
||||
/* From local_external_interrupts_0 */
|
||||
struct __metal_driver_sifive_local_external_interrupts0 __metal_dt_local_external_interrupts_0 = {
|
||||
.irc.vtable = &__metal_driver_vtable_sifive_local_external_interrupts0.local0_vtable,
|
||||
.init_done = 0,
|
||||
};
|
||||
struct metal_pmp __metal_dt_pmp;
|
||||
|
||||
/* From gpio@10012000 */
|
||||
struct __metal_driver_sifive_gpio0 __metal_dt_gpio_10012000 = {
|
||||
.gpio.vtable = &__metal_driver_vtable_sifive_gpio0.gpio,
|
||||
};
|
||||
|
||||
/* From led@0red */
|
||||
struct __metal_driver_sifive_gpio_led __metal_dt_led_0red = {
|
||||
/* From led@0 */
|
||||
struct __metal_driver_sifive_gpio_led __metal_dt_led_0 = {
|
||||
.led.vtable = &__metal_driver_vtable_sifive_led.led_vtable,
|
||||
};
|
||||
|
||||
/* From led@0green */
|
||||
struct __metal_driver_sifive_gpio_led __metal_dt_led_0green = {
|
||||
/* From led@1 */
|
||||
struct __metal_driver_sifive_gpio_led __metal_dt_led_1 = {
|
||||
.led.vtable = &__metal_driver_vtable_sifive_led.led_vtable,
|
||||
};
|
||||
|
||||
/* From led@0blue */
|
||||
struct __metal_driver_sifive_gpio_led __metal_dt_led_0blue = {
|
||||
/* From led@2 */
|
||||
struct __metal_driver_sifive_gpio_led __metal_dt_led_2 = {
|
||||
.led.vtable = &__metal_driver_vtable_sifive_led.led_vtable,
|
||||
};
|
||||
|
||||
/* From i2c@10016000 */
|
||||
struct __metal_driver_sifive_i2c0 __metal_dt_i2c_10016000 = {
|
||||
.i2c.vtable = &__metal_driver_vtable_sifive_i2c0.i2c,
|
||||
};
|
||||
|
||||
/* From pwm@10015000 */
|
||||
struct __metal_driver_sifive_pwm0 __metal_dt_pwm_10015000 = {
|
||||
.pwm.vtable = &__metal_driver_vtable_sifive_pwm0.pwm,
|
||||
};
|
||||
|
||||
/* From pwm@10025000 */
|
||||
struct __metal_driver_sifive_pwm0 __metal_dt_pwm_10025000 = {
|
||||
.pwm.vtable = &__metal_driver_vtable_sifive_pwm0.pwm,
|
||||
};
|
||||
|
||||
/* From pwm@10035000 */
|
||||
struct __metal_driver_sifive_pwm0 __metal_dt_pwm_10035000 = {
|
||||
.pwm.vtable = &__metal_driver_vtable_sifive_pwm0.pwm,
|
||||
};
|
||||
|
||||
/* From aon@10000000 */
|
||||
struct __metal_driver_sifive_rtc0 __metal_dt_rtc_10000000 = {
|
||||
.rtc.vtable = &__metal_driver_vtable_sifive_rtc0.rtc,
|
||||
};
|
||||
|
||||
/* From spi@10014000 */
|
||||
struct __metal_driver_sifive_spi0 __metal_dt_spi_10014000 = {
|
||||
.spi.vtable = &__metal_driver_vtable_sifive_spi0.spi,
|
||||
};
|
||||
|
||||
/* From spi@10024000 */
|
||||
struct __metal_driver_sifive_spi0 __metal_dt_spi_10024000 = {
|
||||
.spi.vtable = &__metal_driver_vtable_sifive_spi0.spi,
|
||||
};
|
||||
|
||||
/* From spi@10034000 */
|
||||
struct __metal_driver_sifive_spi0 __metal_dt_spi_10034000 = {
|
||||
.spi.vtable = &__metal_driver_vtable_sifive_spi0.spi,
|
||||
};
|
||||
|
||||
/* From serial@10013000 */
|
||||
struct __metal_driver_sifive_uart0 __metal_dt_serial_10013000 = {
|
||||
.uart.vtable = &__metal_driver_vtable_sifive_uart0.uart,
|
||||
};
|
||||
|
||||
/* From serial@10023000 */
|
||||
struct __metal_driver_sifive_uart0 __metal_dt_serial_10023000 = {
|
||||
.uart.vtable = &__metal_driver_vtable_sifive_uart0.uart,
|
||||
};
|
||||
|
||||
/* From aon@10000000 */
|
||||
struct __metal_driver_sifive_wdog0 __metal_dt_aon_10000000 = {
|
||||
.watchdog.vtable = &__metal_driver_vtable_sifive_wdog0.watchdog,
|
||||
};
|
||||
|
||||
/* From clock@3 */
|
||||
struct __metal_driver_sifive_fe310_g000_hfrosc __metal_dt_clock_3 = {
|
||||
.clock.vtable = &__metal_driver_vtable_sifive_fe310_g000_hfrosc.clock,
|
||||
|
@ -235,6 +364,11 @@ struct __metal_driver_sifive_fe310_g000_hfxosc __metal_dt_clock_1 = {
|
|||
.clock.vtable = &__metal_driver_vtable_sifive_fe310_g000_hfxosc.clock,
|
||||
};
|
||||
|
||||
/* From clock@7 */
|
||||
struct __metal_driver_sifive_fe310_g000_lfrosc __metal_dt_clock_7 = {
|
||||
.clock.vtable = &__metal_driver_vtable_sifive_fe310_g000_lfrosc.clock,
|
||||
};
|
||||
|
||||
/* From clock@4 */
|
||||
struct __metal_driver_sifive_fe310_g000_pll __metal_dt_clock_4 = {
|
||||
.clock.vtable = &__metal_driver_vtable_sifive_fe310_g000_pll.clock,
|
||||
|
@ -242,8 +376,9 @@ struct __metal_driver_sifive_fe310_g000_pll __metal_dt_clock_4 = {
|
|||
|
||||
/* From prci@10008000 */
|
||||
struct __metal_driver_sifive_fe310_g000_prci __metal_dt_prci_10008000 = {
|
||||
.vtable = &__metal_driver_vtable_sifive_fe310_g000_prci,
|
||||
};
|
||||
|
||||
|
||||
#endif /* SIFIVE_HIFIVE1_REVB____METAL_INLINE_H*/
|
||||
#endif /* METAL_INLINE_H*/
|
||||
#endif /* ! ASSEMBLY */
|
||||
|
|
|
@ -3,8 +3,8 @@
|
|||
/* ----------------------------------- */
|
||||
/* ----------------------------------- */
|
||||
|
||||
#ifndef SIFIVE_HIFIVE1_REVB____METAL_PLATFORM_H
|
||||
#define SIFIVE_HIFIVE1_REVB____METAL_PLATFORM_H
|
||||
#ifndef METAL_PLATFORM_H
|
||||
#define METAL_PLATFORM_H
|
||||
|
||||
/* From clock@0 */
|
||||
#define METAL_FIXED_CLOCK_0_CLOCK_FREQUENCY 16000000UL
|
||||
|
@ -13,7 +13,10 @@
|
|||
#define METAL_FIXED_CLOCK_2_CLOCK_FREQUENCY 72000000UL
|
||||
|
||||
/* From clock@5 */
|
||||
#define METAL_FIXED_CLOCK_5_CLOCK_FREQUENCY 32000000UL
|
||||
#define METAL_FIXED_CLOCK_5_CLOCK_FREQUENCY 32768UL
|
||||
|
||||
/* From clock@6 */
|
||||
#define METAL_FIXED_CLOCK_6_CLOCK_FREQUENCY 32768UL
|
||||
|
||||
#define METAL_FIXED_CLOCK
|
||||
|
||||
|
@ -35,15 +38,18 @@
|
|||
#define METAL_RISCV_PLIC0_0_SIZE 67108864UL
|
||||
#define METAL_RISCV_PLIC0_C000000_RISCV_MAX_PRIORITY 7UL
|
||||
#define METAL_RISCV_PLIC0_0_RISCV_MAX_PRIORITY 7UL
|
||||
#define METAL_RISCV_PLIC0_C000000_RISCV_NDEV 27UL
|
||||
#define METAL_RISCV_PLIC0_0_RISCV_NDEV 27UL
|
||||
#define METAL_RISCV_PLIC0_C000000_RISCV_NDEV 53UL
|
||||
#define METAL_RISCV_PLIC0_0_RISCV_NDEV 53UL
|
||||
|
||||
#define METAL_RISCV_PLIC0
|
||||
#define METAL_RISCV_PLIC0_PRIORITY_BASE 0UL
|
||||
#define METAL_RISCV_PLIC0_PENDING_BASE 4096UL
|
||||
#define METAL_RISCV_PLIC0_ENABLE_BASE 8192UL
|
||||
#define METAL_RISCV_PLIC0_THRESHOLD 2097152UL
|
||||
#define METAL_RISCV_PLIC0_CLAIM 2097156UL
|
||||
#define METAL_RISCV_PLIC0_ENABLE_PER_HART 128UL
|
||||
#define METAL_RISCV_PLIC0_CONTEXT_BASE 2097152UL
|
||||
#define METAL_RISCV_PLIC0_CONTEXT_PER_HART 4096UL
|
||||
#define METAL_RISCV_PLIC0_CONTEXT_THRESHOLD 0UL
|
||||
#define METAL_RISCV_PLIC0_CONTEXT_CLAIM 4UL
|
||||
|
||||
/* From aon@10000000 */
|
||||
#define METAL_SIFIVE_AON0_10000000_BASE_ADDRESS 268435456UL
|
||||
|
@ -111,6 +117,10 @@
|
|||
|
||||
#define METAL_SIFIVE_FE310_G000_HFXOSC
|
||||
|
||||
/* From clock@7 */
|
||||
|
||||
#define METAL_SIFIVE_FE310_G000_LFROSC
|
||||
|
||||
/* From prci@10008000 */
|
||||
#define METAL_SIFIVE_FE310_G000_PRCI_10008000_BASE_ADDRESS 268468224UL
|
||||
#define METAL_SIFIVE_FE310_G000_PRCI_0_BASE_ADDRESS 268468224UL
|
||||
|
@ -153,11 +163,11 @@
|
|||
#define METAL_SIFIVE_GPIO0_IOF_SEL 60UL
|
||||
#define METAL_SIFIVE_GPIO0_OUT_XOR 64UL
|
||||
|
||||
/* From led@0red */
|
||||
/* From led@0 */
|
||||
|
||||
/* From led@0green */
|
||||
/* From led@1 */
|
||||
|
||||
/* From led@0blue */
|
||||
/* From led@2 */
|
||||
|
||||
#define METAL_SIFIVE_GPIO_LEDS
|
||||
|
||||
|
@ -176,16 +186,24 @@
|
|||
#define METAL_SIFIVE_I2C0_COMMAND 16UL
|
||||
#define METAL_SIFIVE_I2C0_STATUS 16UL
|
||||
|
||||
/* From local_external_interrupts_0 */
|
||||
|
||||
#define METAL_SIFIVE_LOCAL_EXTERNAL_INTERRUPTS0
|
||||
|
||||
/* From pwm@10015000 */
|
||||
#define METAL_SIFIVE_PWM0_10015000_BASE_ADDRESS 268521472UL
|
||||
#define METAL_SIFIVE_PWM0_0_BASE_ADDRESS 268521472UL
|
||||
#define METAL_SIFIVE_PWM0_10015000_SIZE 4096UL
|
||||
#define METAL_SIFIVE_PWM0_0_SIZE 4096UL
|
||||
|
||||
/* From pwm@10025000 */
|
||||
#define METAL_SIFIVE_PWM0_10025000_BASE_ADDRESS 268587008UL
|
||||
#define METAL_SIFIVE_PWM0_1_BASE_ADDRESS 268587008UL
|
||||
#define METAL_SIFIVE_PWM0_10025000_SIZE 4096UL
|
||||
#define METAL_SIFIVE_PWM0_1_SIZE 4096UL
|
||||
|
||||
/* From pwm@10035000 */
|
||||
#define METAL_SIFIVE_PWM0_10035000_BASE_ADDRESS 268652544UL
|
||||
#define METAL_SIFIVE_PWM0_2_BASE_ADDRESS 268652544UL
|
||||
#define METAL_SIFIVE_PWM0_10035000_SIZE 4096UL
|
||||
#define METAL_SIFIVE_PWM0_2_SIZE 4096UL
|
||||
|
||||
#define METAL_SIFIVE_PWM0
|
||||
#define METAL_SIFIVE_PWM0_PWMCFG 0UL
|
||||
#define METAL_SIFIVE_PWM0_PWMCOUNT 8UL
|
||||
|
@ -195,12 +213,37 @@
|
|||
#define METAL_SIFIVE_PWM0_PWMCMP2 40UL
|
||||
#define METAL_SIFIVE_PWM0_PWMCMP3 44UL
|
||||
|
||||
/* From aon@10000000 */
|
||||
#define METAL_SIFIVE_AON0_10000000_BASE_ADDRESS 268435456UL
|
||||
#define METAL_SIFIVE_AON0_0_BASE_ADDRESS 268435456UL
|
||||
#define METAL_SIFIVE_AON0_10000000_SIZE 32768UL
|
||||
#define METAL_SIFIVE_AON0_0_SIZE 32768UL
|
||||
|
||||
#define METAL_SIFIVE_RTC0
|
||||
#define METAL_SIFIVE_RTC0_RTCCFG 64UL
|
||||
#define METAL_SIFIVE_RTC0_RTCCOUNTLO 72UL
|
||||
#define METAL_SIFIVE_RTC0_RTCCOUNTHI 76UL
|
||||
#define METAL_SIFIVE_RTC0_RTCS 80UL
|
||||
#define METAL_SIFIVE_RTC0_RTCCMP0 96UL
|
||||
|
||||
/* From spi@10014000 */
|
||||
#define METAL_SIFIVE_SPI0_10014000_BASE_ADDRESS 268517376UL
|
||||
#define METAL_SIFIVE_SPI0_0_BASE_ADDRESS 268517376UL
|
||||
#define METAL_SIFIVE_SPI0_10014000_SIZE 4096UL
|
||||
#define METAL_SIFIVE_SPI0_0_SIZE 4096UL
|
||||
|
||||
/* From spi@10024000 */
|
||||
#define METAL_SIFIVE_SPI0_10024000_BASE_ADDRESS 268582912UL
|
||||
#define METAL_SIFIVE_SPI0_1_BASE_ADDRESS 268582912UL
|
||||
#define METAL_SIFIVE_SPI0_10024000_SIZE 4096UL
|
||||
#define METAL_SIFIVE_SPI0_1_SIZE 4096UL
|
||||
|
||||
/* From spi@10034000 */
|
||||
#define METAL_SIFIVE_SPI0_10034000_BASE_ADDRESS 268648448UL
|
||||
#define METAL_SIFIVE_SPI0_2_BASE_ADDRESS 268648448UL
|
||||
#define METAL_SIFIVE_SPI0_10034000_SIZE 4096UL
|
||||
#define METAL_SIFIVE_SPI0_2_SIZE 4096UL
|
||||
|
||||
#define METAL_SIFIVE_SPI0
|
||||
#define METAL_SIFIVE_SPI0_SCKDIV 0UL
|
||||
#define METAL_SIFIVE_SPI0_SCKMODE 4UL
|
||||
|
@ -225,6 +268,12 @@
|
|||
#define METAL_SIFIVE_UART0_10013000_SIZE 4096UL
|
||||
#define METAL_SIFIVE_UART0_0_SIZE 4096UL
|
||||
|
||||
/* From serial@10023000 */
|
||||
#define METAL_SIFIVE_UART0_10023000_BASE_ADDRESS 268578816UL
|
||||
#define METAL_SIFIVE_UART0_1_BASE_ADDRESS 268578816UL
|
||||
#define METAL_SIFIVE_UART0_10023000_SIZE 4096UL
|
||||
#define METAL_SIFIVE_UART0_1_SIZE 4096UL
|
||||
|
||||
#define METAL_SIFIVE_UART0
|
||||
#define METAL_SIFIVE_UART0_TXDATA 0UL
|
||||
#define METAL_SIFIVE_UART0_RXDATA 4UL
|
||||
|
@ -234,4 +283,20 @@
|
|||
#define METAL_SIFIVE_UART0_IP 20UL
|
||||
#define METAL_SIFIVE_UART0_DIV 24UL
|
||||
|
||||
#endif /* SIFIVE_HIFIVE1_REVB____METAL_PLATFORM_H*/
|
||||
/* From aon@10000000 */
|
||||
#define METAL_SIFIVE_AON0_10000000_BASE_ADDRESS 268435456UL
|
||||
#define METAL_SIFIVE_AON0_0_BASE_ADDRESS 268435456UL
|
||||
#define METAL_SIFIVE_AON0_10000000_SIZE 32768UL
|
||||
#define METAL_SIFIVE_AON0_0_SIZE 32768UL
|
||||
|
||||
#define METAL_SIFIVE_WDOG0
|
||||
#define METAL_SIFIVE_WDOG0_MAGIC_KEY 5370206UL
|
||||
#define METAL_SIFIVE_WDOG0_MAGIC_FOOD 218755085UL
|
||||
#define METAL_SIFIVE_WDOG0_WDOGCFG 0UL
|
||||
#define METAL_SIFIVE_WDOG0_WDOGCOUNT 8UL
|
||||
#define METAL_SIFIVE_WDOG0_WDOGS 16UL
|
||||
#define METAL_SIFIVE_WDOG0_WDOGFEED 24UL
|
||||
#define METAL_SIFIVE_WDOG0_WDOGKEY 28UL
|
||||
#define METAL_SIFIVE_WDOG0_WDOGCMP 32UL
|
||||
|
||||
#endif /* METAL_PLATFORM_H*/
|
||||
|
|
|
@ -4,8 +4,8 @@
|
|||
#ifndef METAL__MEMORY_H
|
||||
#define METAL__MEMORY_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/*!
|
||||
* @file memory.h
|
||||
|
@ -14,11 +14,11 @@
|
|||
*/
|
||||
|
||||
struct _metal_memory_attributes {
|
||||
int R : 1;
|
||||
int W : 1;
|
||||
int X : 1;
|
||||
int C : 1;
|
||||
int A : 1;
|
||||
unsigned int R : 1;
|
||||
unsigned int W : 1;
|
||||
unsigned int X : 1;
|
||||
unsigned int C : 1;
|
||||
unsigned int A : 1;
|
||||
};
|
||||
|
||||
/*!
|
||||
|
@ -37,7 +37,8 @@ struct metal_memory {
|
|||
* that address is mapped.
|
||||
*
|
||||
* @param address The address to query
|
||||
* @return The memory block handle, or NULL if the address is not mapped to a memory block
|
||||
* @return The memory block handle, or NULL if the address is not mapped to a
|
||||
* memory block
|
||||
*/
|
||||
struct metal_memory *metal_get_memory_from_address(const uintptr_t address);
|
||||
|
||||
|
@ -46,7 +47,8 @@ struct metal_memory *metal_get_memory_from_address(const uintptr_t address);
|
|||
* @param memory The handle for the memory block
|
||||
* @return The base address of the memory block
|
||||
*/
|
||||
inline uintptr_t metal_memory_get_base_address(const struct metal_memory *memory) {
|
||||
__inline__ uintptr_t
|
||||
metal_memory_get_base_address(const struct metal_memory *memory) {
|
||||
return memory->_base_address;
|
||||
}
|
||||
|
||||
|
@ -55,7 +57,7 @@ inline uintptr_t metal_memory_get_base_address(const struct metal_memory *memory
|
|||
* @param memory The handle for the memory block
|
||||
* @return The size of the memory block
|
||||
*/
|
||||
inline size_t metal_memory_get_size(const struct metal_memory *memory) {
|
||||
__inline__ size_t metal_memory_get_size(const struct metal_memory *memory) {
|
||||
return memory->_size;
|
||||
}
|
||||
|
||||
|
@ -64,7 +66,8 @@ inline size_t metal_memory_get_size(const struct metal_memory *memory) {
|
|||
* @param memory The handle for the memory block
|
||||
* @return nonzero if the memory block supports atomic operations
|
||||
*/
|
||||
inline int metal_memory_supports_atomics(const struct metal_memory *memory) {
|
||||
__inline__ int
|
||||
metal_memory_supports_atomics(const struct metal_memory *memory) {
|
||||
return memory->_attrs.A;
|
||||
}
|
||||
|
||||
|
@ -73,9 +76,8 @@ inline int metal_memory_supports_atomics(const struct metal_memory *memory) {
|
|||
* @param memory The handle for the memory block
|
||||
* @return nonzero if the memory block is cachable
|
||||
*/
|
||||
inline int metal_memory_is_cachable(const struct metal_memory *memory) {
|
||||
__inline__ int metal_memory_is_cachable(const struct metal_memory *memory) {
|
||||
return memory->_attrs.C;
|
||||
}
|
||||
|
||||
#endif /* METAL__MEMORY_H */
|
||||
|
||||
|
|
|
@ -18,8 +18,8 @@
|
|||
* can be found by reading the RISC-V Privileged Architecture Specification.
|
||||
*/
|
||||
|
||||
#include <stddef.h>
|
||||
#include <metal/machine.h>
|
||||
#include <stddef.h>
|
||||
|
||||
struct metal_pmp;
|
||||
|
||||
|
@ -42,11 +42,11 @@ enum metal_pmp_address_mode {
|
|||
*/
|
||||
struct metal_pmp_config {
|
||||
/*! @brief Sets whether reads to the PMP region succeed */
|
||||
int R : 1;
|
||||
unsigned int R : 1;
|
||||
/*! @brief Sets whether writes to the PMP region succeed */
|
||||
int W : 1;
|
||||
unsigned int W : 1;
|
||||
/*! @brief Sets whether the PMP region is executable */
|
||||
int X : 1;
|
||||
unsigned int X : 1;
|
||||
|
||||
/*! @brief Sets the addressing mode of the PMP region */
|
||||
enum metal_pmp_address_mode A : 2;
|
||||
|
@ -73,6 +73,11 @@ struct metal_pmp {
|
|||
*/
|
||||
struct metal_pmp *metal_pmp_get_device(void);
|
||||
|
||||
/*!
|
||||
* @brief Get the number of pmp regions for the hartid
|
||||
*/
|
||||
int metal_pmp_num_regions(int hartid);
|
||||
|
||||
/*!
|
||||
* @brief Initialize the PMP
|
||||
* @param pmp The PMP device handle to be initialized
|
||||
|
@ -96,7 +101,8 @@ void metal_pmp_init(struct metal_pmp *pmp);
|
|||
* @param address The desired address of the PMP region
|
||||
* @return 0 upon success
|
||||
*/
|
||||
int metal_pmp_set_region(struct metal_pmp *pmp, unsigned int region, struct metal_pmp_config config, size_t address);
|
||||
int metal_pmp_set_region(struct metal_pmp *pmp, unsigned int region,
|
||||
struct metal_pmp_config config, size_t address);
|
||||
|
||||
/*!
|
||||
* @brief Get the configuration for a PMP region
|
||||
|
@ -106,7 +112,8 @@ int metal_pmp_set_region(struct metal_pmp *pmp, unsigned int region, struct meta
|
|||
* @param address Variable to store the PMP region address
|
||||
* @return 0 if the region is read successfully
|
||||
*/
|
||||
int metal_pmp_get_region(struct metal_pmp *pmp, unsigned int region, struct metal_pmp_config *config, size_t *address);
|
||||
int metal_pmp_get_region(struct metal_pmp *pmp, unsigned int region,
|
||||
struct metal_pmp_config *config, size_t *address);
|
||||
|
||||
/*!
|
||||
* @brief Lock a PMP region
|
||||
|
@ -123,7 +130,8 @@ int metal_pmp_lock(struct metal_pmp *pmp, unsigned int region);
|
|||
* @param address The desired address of the PMP region
|
||||
* @return 0 if the address is successfully set
|
||||
*/
|
||||
int metal_pmp_set_address(struct metal_pmp *pmp, unsigned int region, size_t address);
|
||||
int metal_pmp_set_address(struct metal_pmp *pmp, unsigned int region,
|
||||
size_t address);
|
||||
|
||||
/*!
|
||||
* @brief Get the address of a PMP region
|
||||
|
@ -140,7 +148,8 @@ size_t metal_pmp_get_address(struct metal_pmp *pmp, unsigned int region);
|
|||
* @param mode The PMP addressing mode to set
|
||||
* @return 0 if the addressing mode is successfully set
|
||||
*/
|
||||
int metal_pmp_set_address_mode(struct metal_pmp *pmp, unsigned int region, enum metal_pmp_address_mode mode);
|
||||
int metal_pmp_set_address_mode(struct metal_pmp *pmp, unsigned int region,
|
||||
enum metal_pmp_address_mode mode);
|
||||
|
||||
/*!
|
||||
* @brief Get the addressing mode of a PMP region
|
||||
|
@ -148,7 +157,8 @@ int metal_pmp_set_address_mode(struct metal_pmp *pmp, unsigned int region, enum
|
|||
* @param region The PMP region to read
|
||||
* @return The address mode of the PMP region
|
||||
*/
|
||||
enum metal_pmp_address_mode metal_pmp_get_address_mode(struct metal_pmp *pmp, unsigned int region);
|
||||
enum metal_pmp_address_mode metal_pmp_get_address_mode(struct metal_pmp *pmp,
|
||||
unsigned int region);
|
||||
|
||||
/*!
|
||||
* @brief Set the executable bit for a PMP region
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
enum metal_privilege_mode {
|
||||
METAL_PRIVILEGE_USER = 0,
|
||||
METAL_PRIVILEGE_SUPERVISOR = 1,
|
||||
METAL_PRIVELEGE_MACHINE = 3,
|
||||
METAL_PRIVILEGE_MACHINE = 3,
|
||||
};
|
||||
|
||||
#if __riscv_xlen == 32
|
||||
|
@ -113,7 +113,7 @@ struct metal_register_file {
|
|||
#endif /* __riscv_flen */
|
||||
};
|
||||
|
||||
typedef void (*metal_privilege_entry_point_t)();
|
||||
typedef void (*metal_privilege_entry_point_t)(void);
|
||||
|
||||
void metal_privilege_drop_to_mode(enum metal_privilege_mode mode,
|
||||
struct metal_register_file regfile,
|
||||
|
|
|
@ -0,0 +1,162 @@
|
|||
/* Copyright 2020 SiFive, Inc */
|
||||
/* SPDX-License-Identifier: Apache-2.0 */
|
||||
|
||||
#ifndef METAL__PWM_H
|
||||
#define METAL__PWM_H
|
||||
|
||||
/*! @brief Enums for PWM running modes. */
|
||||
typedef enum {
|
||||
METAL_PWM_CONTINUOUS = 0,
|
||||
METAL_PWM_ONE_SHOT = 1
|
||||
} metal_pwm_run_mode_t;
|
||||
|
||||
/*! @brief Enums for Phase correct PWM. */
|
||||
typedef enum {
|
||||
METAL_PWM_PHASE_CORRECT_DISABLE = 0,
|
||||
METAL_PWM_PHASE_CORRECT_ENABLE = 1,
|
||||
} metal_pwm_phase_correct_t;
|
||||
|
||||
/*! @brief Enums for Interrupts enable/disable. */
|
||||
typedef enum {
|
||||
METAL_PWM_INTERRUPT_DISABLE = 0,
|
||||
METAL_PWM_INTERRUPT_ENABLE = 1,
|
||||
} metal_pwm_interrupt_t;
|
||||
|
||||
struct metal_pwm;
|
||||
|
||||
/*! @brief vtable for PWM. */
|
||||
struct metal_pwm_vtable {
|
||||
int (*enable)(struct metal_pwm *pwm);
|
||||
int (*disable)(struct metal_pwm *pwm);
|
||||
int (*set_freq)(struct metal_pwm *pwm, unsigned int idx, unsigned int freq);
|
||||
int (*set_duty)(struct metal_pwm *pwm, unsigned int idx, unsigned int duty,
|
||||
metal_pwm_phase_correct_t phase_corr);
|
||||
unsigned int (*get_duty)(struct metal_pwm *pwm, unsigned int idx);
|
||||
unsigned int (*get_freq)(struct metal_pwm *pwm, unsigned int idx);
|
||||
int (*trigger)(struct metal_pwm *pwm, unsigned int idx,
|
||||
metal_pwm_run_mode_t mode);
|
||||
int (*stop)(struct metal_pwm *pwm, unsigned int idx);
|
||||
int (*cfg_interrupt)(struct metal_pwm *pwm, metal_pwm_interrupt_t flag);
|
||||
int (*clr_interrupt)(struct metal_pwm *pwm, unsigned int idx);
|
||||
struct metal_interrupt *(*get_interrupt_controller)(struct metal_pwm *pwm);
|
||||
int (*get_interrupt_id)(struct metal_pwm *pwm, unsigned int idx);
|
||||
};
|
||||
|
||||
/*! @brief A handle for a PWM device. */
|
||||
struct metal_pwm {
|
||||
const struct metal_pwm_vtable *vtable;
|
||||
};
|
||||
|
||||
/*! @brief Gets a PWM device handle.
|
||||
* @param device_num The index of the desired PWM device.
|
||||
* @return A handle to the PWM device, or NULL if the device does not exist.*/
|
||||
struct metal_pwm *metal_pwm_get_device(unsigned int device_num);
|
||||
|
||||
/*! @brief Enables PWM operation.
|
||||
* @param pwm The handle for the PWM device to initialize.
|
||||
* @return 0 If no error.*/
|
||||
inline int metal_pwm_enable(struct metal_pwm *pwm) {
|
||||
return pwm->vtable->enable(pwm);
|
||||
}
|
||||
|
||||
/*! @brief Disables PWM operation.
|
||||
* @param pwm The handle for the PWM device to be disabled.
|
||||
* @return 0 If no error.*/
|
||||
inline int metal_pwm_disable(struct metal_pwm *pwm) {
|
||||
return pwm->vtable->disable(pwm);
|
||||
}
|
||||
|
||||
/*! @brief Sets frequency in Hz for a given PWM instance.
|
||||
* @param pwm PWM device handle.
|
||||
* @param idx PWM channel id.
|
||||
* @param freq PWM frequency in Hz.
|
||||
* @return 0 If no error.*/
|
||||
inline int metal_pwm_set_freq(struct metal_pwm *pwm, unsigned int idx,
|
||||
unsigned int freq) {
|
||||
return pwm->vtable->set_freq(pwm, idx, freq);
|
||||
}
|
||||
|
||||
/*! @brief Sets duty cycle in percent values [0 - 100] for a given PWM instance.
|
||||
* Phase correct mode provides center aligned PWM waveform output.
|
||||
* @param pwm PWM device handle.
|
||||
* @param idx PWM channel id.
|
||||
* @param duty PWM duty cycle value.
|
||||
* @param phase_corr Enable / Disable phase correct mode.
|
||||
* @return 0 If no error.*/
|
||||
inline int metal_pwm_set_duty(struct metal_pwm *pwm, unsigned int idx,
|
||||
unsigned int duty,
|
||||
metal_pwm_phase_correct_t phase_corr) {
|
||||
return pwm->vtable->set_duty(pwm, idx, duty, phase_corr);
|
||||
}
|
||||
|
||||
/*! @brief Gets duty cycle in percent values [0 - 100] for a given PWM instance.
|
||||
* @param pwm PWM device handle.
|
||||
* @param idx PWM channel id.
|
||||
* @return PWM duty cycle value.*/
|
||||
inline unsigned int metal_pwm_get_duty(struct metal_pwm *pwm,
|
||||
unsigned int idx) {
|
||||
return pwm->vtable->get_duty(pwm, idx);
|
||||
}
|
||||
|
||||
/*! @brief Gets frequency in Hz for a given PWM instance.
|
||||
* @param pwm PWM device handle.
|
||||
* @param idx PWM channel id.
|
||||
* @return PWM frequency in Hz.*/
|
||||
inline unsigned int metal_pwm_get_freq(struct metal_pwm *pwm,
|
||||
unsigned int idx) {
|
||||
return pwm->vtable->get_freq(pwm, idx);
|
||||
}
|
||||
|
||||
/*! @brief Starts a PWM instance in selected run mode (continuous/one shot).
|
||||
* @param pwm PWM device handle.
|
||||
* @param idx PWM channel id.
|
||||
* @return 0 If no error.*/
|
||||
inline int metal_pwm_trigger(struct metal_pwm *pwm, unsigned int idx,
|
||||
metal_pwm_run_mode_t mode) {
|
||||
return pwm->vtable->trigger(pwm, idx, mode);
|
||||
}
|
||||
|
||||
/*! @brief Stops a running PWM instance in continuous mode.
|
||||
* @param pwm PWM device handle.
|
||||
* @param idx PWM channel id.
|
||||
* @return 0 If no error.*/
|
||||
inline int metal_pwm_stop(struct metal_pwm *pwm, unsigned int idx) {
|
||||
return pwm->vtable->stop(pwm, idx);
|
||||
}
|
||||
|
||||
/*! @brief Enable or Disable PWM interrupts.
|
||||
* @param pwm PWM device handle.
|
||||
* @param flag PWM interrupt enable flag.
|
||||
* @return 0 If no error.*/
|
||||
inline int metal_pwm_cfg_interrupt(struct metal_pwm *pwm,
|
||||
metal_pwm_interrupt_t flag) {
|
||||
return pwm->vtable->cfg_interrupt(pwm, flag);
|
||||
}
|
||||
|
||||
/*! @brief Clears pending interrupt flags.
|
||||
* @param pwm PWM device handle.
|
||||
* @param idx PWM channel id.
|
||||
* @return 0 If no error.*/
|
||||
inline int metal_pwm_clr_interrupt(struct metal_pwm *pwm, unsigned int idx) {
|
||||
return pwm->vtable->clr_interrupt(pwm, idx);
|
||||
}
|
||||
|
||||
/*! @brief Get the interrupt controller of the PWM peripheral.
|
||||
* The interrupt controller must be initialized before any interrupts can be
|
||||
* registered or enabled with it.
|
||||
* @param pwm PWM device handle.
|
||||
* @return The handle for the PWM interrupt controller.*/
|
||||
inline struct metal_interrupt *
|
||||
metal_pwm_interrupt_controller(struct metal_pwm *pwm) {
|
||||
return pwm->vtable->get_interrupt_controller(pwm);
|
||||
}
|
||||
|
||||
/*! @brief Get the interrupt ID of the PWM peripheral.
|
||||
* @param pwm PWM device handle.
|
||||
* @param idx PWM channel id.
|
||||
* @return The PWM interrupt id.*/
|
||||
inline int metal_pwm_get_interrupt_id(struct metal_pwm *pwm, unsigned int idx) {
|
||||
return pwm->vtable->get_interrupt_id(pwm, idx);
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,137 @@
|
|||
/* Copyright 2019 SiFive, Inc. */
|
||||
/* SPDX-License-Identifier: Apache-2.0 */
|
||||
|
||||
#ifndef METAL__RTC_H
|
||||
#define METAL__RTC_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/*!
|
||||
* @file rtc.h
|
||||
* @brief API for Real-Time Clocks
|
||||
*/
|
||||
|
||||
struct metal_rtc;
|
||||
|
||||
/*!
|
||||
* @brief List of RTC run behaviors
|
||||
*/
|
||||
enum metal_rtc_run_option {
|
||||
METAL_RTC_STOP = 0,
|
||||
METAL_RTC_RUN,
|
||||
};
|
||||
|
||||
struct metal_rtc_vtable {
|
||||
uint64_t (*get_rate)(const struct metal_rtc *const rtc);
|
||||
uint64_t (*set_rate)(const struct metal_rtc *const rtc,
|
||||
const uint64_t rate);
|
||||
uint64_t (*get_compare)(const struct metal_rtc *const rtc);
|
||||
uint64_t (*set_compare)(const struct metal_rtc *const rtc,
|
||||
const uint64_t compare);
|
||||
uint64_t (*get_count)(const struct metal_rtc *const rtc);
|
||||
uint64_t (*set_count)(const struct metal_rtc *const rtc,
|
||||
const uint64_t count);
|
||||
int (*run)(const struct metal_rtc *const rtc,
|
||||
const enum metal_rtc_run_option option);
|
||||
struct metal_interrupt *(*get_interrupt)(const struct metal_rtc *const rtc);
|
||||
int (*get_interrupt_id)(const struct metal_rtc *const rtc);
|
||||
};
|
||||
|
||||
/*!
|
||||
* @brief Handle for a Real-Time Clock
|
||||
*/
|
||||
struct metal_rtc {
|
||||
const struct metal_rtc_vtable *vtable;
|
||||
};
|
||||
|
||||
/*!
|
||||
* @brief Get the rate of the RTC
|
||||
* @return The rate in Hz
|
||||
*/
|
||||
inline uint64_t metal_rtc_get_rate(const struct metal_rtc *const rtc) {
|
||||
return rtc->vtable->get_rate(rtc);
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Set (if possible) the rate of the RTC
|
||||
* @return The new rate of the RTC (not guaranteed to be the same as requested)
|
||||
*/
|
||||
inline uint64_t metal_rtc_set_rate(const struct metal_rtc *const rtc,
|
||||
const uint64_t rate) {
|
||||
return rtc->vtable->set_rate(rtc, rate);
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Get the compare value of the RTC
|
||||
* @return The compare value
|
||||
*/
|
||||
inline uint64_t metal_rtc_get_compare(const struct metal_rtc *const rtc) {
|
||||
return rtc->vtable->get_compare(rtc);
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Set the compare value of the RTC
|
||||
* @return The set compare value (not guaranteed to be exactly the requested
|
||||
* value)
|
||||
*
|
||||
* The RTC device might impose limits on the maximum compare value or the
|
||||
* granularity of the compare value.
|
||||
*/
|
||||
inline uint64_t metal_rtc_set_compare(const struct metal_rtc *const rtc,
|
||||
const uint64_t compare) {
|
||||
return rtc->vtable->set_compare(rtc, compare);
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Get the current count of the RTC
|
||||
* @return The count
|
||||
*/
|
||||
inline uint64_t metal_rtc_get_count(const struct metal_rtc *const rtc) {
|
||||
return rtc->vtable->get_count(rtc);
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Set the current count of the RTC
|
||||
* @return The set value of the count (not guaranteed to be exactly the
|
||||
* requested value)
|
||||
*
|
||||
* The RTC device might impose limits on the maximum value of the count
|
||||
*/
|
||||
inline uint64_t metal_rtc_set_count(const struct metal_rtc *const rtc,
|
||||
const uint64_t count) {
|
||||
return rtc->vtable->set_count(rtc, count);
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Start or stop the RTC
|
||||
* @return 0 if the RTC was successfully started/stopped
|
||||
*/
|
||||
inline int metal_rtc_run(const struct metal_rtc *const rtc,
|
||||
const enum metal_rtc_run_option option) {
|
||||
return rtc->vtable->run(rtc, option);
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Get the interrupt handle for the RTC compare
|
||||
* @return The interrupt handle
|
||||
*/
|
||||
inline struct metal_interrupt *
|
||||
metal_rtc_get_interrupt(const struct metal_rtc *const rtc) {
|
||||
return rtc->vtable->get_interrupt(rtc);
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Get the interrupt ID for the RTC compare
|
||||
* @return The interrupt ID
|
||||
*/
|
||||
inline int metal_rtc_get_interrupt_id(const struct metal_rtc *const rtc) {
|
||||
return rtc->vtable->get_interrupt_id(rtc);
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Get the handle for an RTC by index
|
||||
* @return The RTC handle, or NULL if none is available at that index
|
||||
*/
|
||||
struct metal_rtc *metal_rtc_get_device(int index);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,13 @@
|
|||
/* Copyright 2020 SiFive, Inc */
|
||||
/* SPDX-License-Identifier: Apache-2.0 */
|
||||
|
||||
#ifndef METAL__SCRUB_H
|
||||
#define METAL__SCRUB_H
|
||||
|
||||
/*! @brief Writes specified memory region with zeros.
|
||||
* @param address Start memory address for zero-scrub.
|
||||
* @param size Memory region size in bytes.
|
||||
* @return None.*/
|
||||
void metal_mem_scrub(void *address, int size);
|
||||
|
||||
#endif
|
|
@ -12,15 +12,20 @@
|
|||
struct __metal_shutdown;
|
||||
|
||||
struct __metal_shutdown_vtable {
|
||||
void (*exit)(const struct __metal_shutdown *sd, int code) __attribute__((noreturn));
|
||||
void (*exit)(const struct __metal_shutdown *sd, int code)
|
||||
__attribute__((noreturn));
|
||||
};
|
||||
|
||||
struct __metal_shutdown {
|
||||
const struct __metal_shutdown_vtable *vtable;
|
||||
};
|
||||
|
||||
inline void __metal_shutdown_exit(const struct __metal_shutdown *sd, int code) __attribute__((noreturn));
|
||||
inline void __metal_shutdown_exit(const struct __metal_shutdown *sd, int code) { sd->vtable->exit(sd, code); }
|
||||
__inline__ void __metal_shutdown_exit(const struct __metal_shutdown *sd,
|
||||
int code) __attribute__((noreturn));
|
||||
__inline__ void __metal_shutdown_exit(const struct __metal_shutdown *sd,
|
||||
int code) {
|
||||
sd->vtable->exit(sd, code);
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief The public METAL shutdown interface
|
||||
|
|
|
@ -9,11 +9,7 @@ struct metal_spi;
|
|||
/*! @brief The configuration for a SPI transfer */
|
||||
struct metal_spi_config {
|
||||
/*! @brief The protocol for the SPI transfer */
|
||||
enum {
|
||||
METAL_SPI_SINGLE,
|
||||
METAL_SPI_DUAL,
|
||||
METAL_SPI_QUAD
|
||||
} protocol;
|
||||
enum { METAL_SPI_SINGLE, METAL_SPI_DUAL, METAL_SPI_QUAD } protocol;
|
||||
|
||||
/*! @brief The polarity of the SPI transfer, equivalent to CPOL */
|
||||
unsigned int polarity : 1;
|
||||
|
@ -25,11 +21,24 @@ struct metal_spi_config {
|
|||
unsigned int cs_active_high : 1;
|
||||
/*! @brief The chip select ID to activate for the SPI transfer */
|
||||
unsigned int csid;
|
||||
/*! @brief The spi command frame number (cycles = num * frame_len) */
|
||||
unsigned int cmd_num;
|
||||
/*! @brief The spi address frame number */
|
||||
unsigned int addr_num;
|
||||
/*! @brief The spi dummy frame number */
|
||||
unsigned int dummy_num;
|
||||
/*! @brief The Dual/Quad spi mode selection.*/
|
||||
enum {
|
||||
MULTI_WIRE_ALL,
|
||||
MULTI_WIRE_DATA_ONLY,
|
||||
MULTI_WIRE_ADDR_DATA
|
||||
} multi_wire;
|
||||
};
|
||||
|
||||
struct metal_spi_vtable {
|
||||
void (*init)(struct metal_spi *spi, int baud_rate);
|
||||
int (*transfer)(struct metal_spi *spi, struct metal_spi_config *config, size_t len, char *tx_buf, char *rx_buf);
|
||||
int (*transfer)(struct metal_spi *spi, struct metal_spi_config *config,
|
||||
size_t len, char *tx_buf, char *rx_buf);
|
||||
int (*get_baud_rate)(struct metal_spi *spi);
|
||||
int (*set_baud_rate)(struct metal_spi *spi, int baud_rate);
|
||||
};
|
||||
|
@ -42,23 +51,29 @@ struct metal_spi {
|
|||
/*! @brief Get a handle for a SPI device
|
||||
* @param device_num The index of the desired SPI device
|
||||
* @return A handle to the SPI device, or NULL if the device does not exist*/
|
||||
struct metal_spi *metal_spi_get_device(int device_num);
|
||||
struct metal_spi *metal_spi_get_device(unsigned int device_num);
|
||||
|
||||
/*! @brief Initialize a SPI device with a certain baud rate
|
||||
* @param spi The handle for the SPI device to initialize
|
||||
* @param baud_rate The baud rate to set the SPI device to
|
||||
*/
|
||||
inline void metal_spi_init(struct metal_spi *spi, int baud_rate) { spi->vtable->init(spi, baud_rate); }
|
||||
__inline__ void metal_spi_init(struct metal_spi *spi, int baud_rate) {
|
||||
spi->vtable->init(spi, baud_rate);
|
||||
}
|
||||
|
||||
/*! @brief Perform a SPI transfer
|
||||
* @param spi The handle for the SPI device to perform the transfer
|
||||
* @param config The configuration for the SPI transfer.
|
||||
* @param len The number of bytes to transfer
|
||||
* @param tx_buf The buffer to send over the SPI bus. Must be len bytes long. If NULL, the SPI will transfer the value 0.
|
||||
* @param rx_buf The buffer to receive data into. Must be len bytes long. If NULL, the SPI will ignore received bytes.
|
||||
* @param tx_buf The buffer to send over the SPI bus. Must be len bytes long. If
|
||||
* NULL, the SPI will transfer the value 0.
|
||||
* @param rx_buf The buffer to receive data into. Must be len bytes long. If
|
||||
* NULL, the SPI will ignore received bytes.
|
||||
* @return 0 if the transfer succeeds
|
||||
*/
|
||||
inline int metal_spi_transfer(struct metal_spi *spi, struct metal_spi_config *config, size_t len, char *tx_buf, char *rx_buf) {
|
||||
__inline__ int metal_spi_transfer(struct metal_spi *spi,
|
||||
struct metal_spi_config *config, size_t len,
|
||||
char *tx_buf, char *rx_buf) {
|
||||
return spi->vtable->transfer(spi, config, len, tx_buf, rx_buf);
|
||||
}
|
||||
|
||||
|
@ -66,13 +81,17 @@ inline int metal_spi_transfer(struct metal_spi *spi, struct metal_spi_config *co
|
|||
* @param spi The handle for the SPI device
|
||||
* @return The baud rate in Hz
|
||||
*/
|
||||
inline int metal_spi_get_baud_rate(struct metal_spi *spi) { return spi->vtable->get_baud_rate(spi); }
|
||||
__inline__ int metal_spi_get_baud_rate(struct metal_spi *spi) {
|
||||
return spi->vtable->get_baud_rate(spi);
|
||||
}
|
||||
|
||||
/*! @brief Set the current baud rate of the SPI device
|
||||
* @param spi The handle for the SPI device
|
||||
* @param baud_rate The desired baud rate of the SPI device
|
||||
* @return 0 if the baud rate is successfully changed
|
||||
*/
|
||||
inline int metal_spi_set_baud_rate(struct metal_spi *spi, int baud_rate) { return spi->vtable->set_baud_rate(spi, baud_rate); }
|
||||
__inline__ int metal_spi_set_baud_rate(struct metal_spi *spi, int baud_rate) {
|
||||
return spi->vtable->set_baud_rate(spi, baud_rate);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -29,7 +29,8 @@ struct metal_switch {
|
|||
/*!
|
||||
* @brief Get a handle for a switch
|
||||
* @param label The DeviceTree label for the desired switch
|
||||
* @return A handle to the switch, or NULL if none is found for the requested label
|
||||
* @return A handle to the switch, or NULL if none is found for the requested
|
||||
* label
|
||||
*/
|
||||
struct metal_switch *metal_switch_get(char *label);
|
||||
|
||||
|
@ -38,14 +39,18 @@ struct metal_switch* metal_switch_get(char *label);
|
|||
* @param sw The handle for the switch
|
||||
* @return The interrupt controller handle
|
||||
*/
|
||||
inline struct metal_interrupt*
|
||||
metal_switch_interrupt_controller(struct metal_switch *sw) { return sw->vtable->interrupt_controller(sw); }
|
||||
__inline__ struct metal_interrupt *
|
||||
metal_switch_interrupt_controller(struct metal_switch *sw) {
|
||||
return sw->vtable->interrupt_controller(sw);
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Get the interrupt id for a switch
|
||||
* @param sw The handle for the switch
|
||||
* @return The interrupt ID for the switch
|
||||
*/
|
||||
inline int metal_switch_get_interrupt_id(struct metal_switch *sw) { return sw->vtable->get_interrupt_id(sw); }
|
||||
__inline__ int metal_switch_get_interrupt_id(struct metal_switch *sw) {
|
||||
return sw->vtable->get_interrupt_id(sw);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
/* Copyright 2019 SiFive, Inc */
|
||||
/* SPDX-License-Identifier: Apache-2.0 */
|
||||
|
||||
#ifndef METAL__TIME_H
|
||||
#define METAL__TIME_H
|
||||
|
||||
#include <time.h>
|
||||
#ifndef __SEGGER_LIBC__
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
|
||||
/*!
|
||||
* @file time.h
|
||||
* @brief API for dealing with time
|
||||
*/
|
||||
|
||||
int metal_gettimeofday(struct timeval *tp, void *tzp);
|
||||
|
||||
time_t metal_time(void);
|
||||
|
||||
#endif
|
|
@ -23,7 +23,8 @@ int metal_timer_get_cyclecount(int hartid, unsigned long long *cyclecount);
|
|||
* @param timebase The variable to hold the value
|
||||
* @return 0 upon success
|
||||
*/
|
||||
int metal_timer_get_timebase_frequency(int hartid, unsigned long long *timebase);
|
||||
int metal_timer_get_timebase_frequency(int hartid,
|
||||
unsigned long long *timebase);
|
||||
|
||||
/*!
|
||||
* @brief Set the machine timer tick interval in seconds
|
||||
|
|
|
@ -18,6 +18,18 @@
|
|||
* @param c The character to write to the terminal
|
||||
* @return 0 on success, or -1 on failure.
|
||||
*/
|
||||
int metal_tty_putc(unsigned char c);
|
||||
int metal_tty_putc(int c);
|
||||
|
||||
/*!
|
||||
* @brief Get a byte from the default output device
|
||||
*
|
||||
* The default output device, is typically the UART serial port.
|
||||
*
|
||||
* This call is non-blocking, if nothing is ready c==-1
|
||||
* if something is ready, then c=[0x00 to 0xff] byte value.
|
||||
*
|
||||
* @return 0 on success, or -1 on failure.
|
||||
*/
|
||||
int metal_tty_getc(int *c);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -12,15 +12,25 @@
|
|||
#include <metal/interrupt.h>
|
||||
|
||||
struct metal_uart;
|
||||
|
||||
#undef getc
|
||||
#undef putc
|
||||
struct metal_uart_vtable {
|
||||
void (*init)(struct metal_uart *uart, int baud_rate);
|
||||
int (*putc)(struct metal_uart *uart, unsigned char c);
|
||||
int (*getc)(struct metal_uart *uart, unsigned char *c);
|
||||
int (*putc)(struct metal_uart *uart, int c);
|
||||
int (*txready)(struct metal_uart *uart);
|
||||
int (*getc)(struct metal_uart *uart, int *c);
|
||||
int (*get_baud_rate)(struct metal_uart *uart);
|
||||
int (*set_baud_rate)(struct metal_uart *uart, int baud_rate);
|
||||
struct metal_interrupt *(*controller_interrupt)(struct metal_uart *uart);
|
||||
int (*get_interrupt_id)(struct metal_uart *uart);
|
||||
int (*tx_interrupt_enable)(struct metal_uart *uart);
|
||||
int (*tx_interrupt_disable)(struct metal_uart *uart);
|
||||
int (*rx_interrupt_enable)(struct metal_uart *uart);
|
||||
int (*rx_interrupt_disable)(struct metal_uart *uart);
|
||||
int (*set_tx_watermark)(struct metal_uart *uart, size_t length);
|
||||
size_t (*get_tx_watermark)(struct metal_uart *uart);
|
||||
int (*set_rx_watermark)(struct metal_uart *uart, size_t length);
|
||||
size_t (*get_rx_watermark)(struct metal_uart *uart);
|
||||
};
|
||||
|
||||
/*!
|
||||
|
@ -30,16 +40,25 @@ struct metal_uart {
|
|||
const struct metal_uart_vtable *vtable;
|
||||
};
|
||||
|
||||
/*! @brief Get a handle for a UART device
|
||||
* @param device_num The index of the desired UART device
|
||||
* @return A handle to the UART device, or NULL if the device does not exist*/
|
||||
struct metal_uart *metal_uart_get_device(unsigned int device_num);
|
||||
|
||||
/*!
|
||||
* @brief Initialize UART device
|
||||
|
||||
* Initialize the UART device described by the UART handle. This function must be called before any
|
||||
* other method on the UART can be invoked. It is invalid to initialize a UART more than once.
|
||||
* Initialize the UART device described by the UART handle. This function must
|
||||
be called before any
|
||||
* other method on the UART can be invoked. It is invalid to initialize a UART
|
||||
more than once.
|
||||
*
|
||||
* @param uart The UART device handle
|
||||
* @param baud_rate the baud rate to set the UART to
|
||||
*/
|
||||
inline void metal_uart_init(struct metal_uart *uart, int baud_rate) { return uart->vtable->init(uart, baud_rate); }
|
||||
__inline__ void metal_uart_init(struct metal_uart *uart, int baud_rate) {
|
||||
uart->vtable->init(uart, baud_rate);
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Output a character over the UART
|
||||
|
@ -47,22 +66,40 @@ inline void metal_uart_init(struct metal_uart *uart, int baud_rate) { return uar
|
|||
* @param c The character to send over the UART
|
||||
* @return 0 upon success
|
||||
*/
|
||||
inline int metal_uart_putc(struct metal_uart *uart, unsigned char c) { return uart->vtable->putc(uart, c); }
|
||||
__inline__ int metal_uart_putc(struct metal_uart *uart, int c) {
|
||||
return uart->vtable->putc(uart, c);
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Test, determine if tx output is blocked(full/busy)
|
||||
* @param uart The UART device handle
|
||||
* @return 0 not blocked
|
||||
*/
|
||||
__inline__ int metal_uart_txready(struct metal_uart *uart) {
|
||||
return uart->vtable->txready(uart);
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Read a character sent over the UART
|
||||
* @param uart The UART device handle
|
||||
* @param c The varible to hold the read character
|
||||
* @return 0 upon success
|
||||
*
|
||||
* If "c == -1" no char was ready.
|
||||
* If "c != -1" then C == byte value (0x00 to 0xff)
|
||||
*/
|
||||
inline int metal_uart_getc(struct metal_uart *uart, unsigned char *c) { return uart->vtable->getc(uart, c); }
|
||||
__inline__ int metal_uart_getc(struct metal_uart *uart, int *c) {
|
||||
return uart->vtable->getc(uart, c);
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Get the baud rate of the UART peripheral
|
||||
* @param uart The UART device handle
|
||||
* @return The current baud rate of the UART
|
||||
*/
|
||||
inline int metal_uart_get_baud_rate(struct metal_uart *uart) { return uart->vtable->get_baud_rate(uart); }
|
||||
__inline__ int metal_uart_get_baud_rate(struct metal_uart *uart) {
|
||||
return uart->vtable->get_baud_rate(uart);
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Set the baud rate of the UART peripheral
|
||||
|
@ -70,7 +107,10 @@ inline int metal_uart_get_baud_rate(struct metal_uart *uart) { return uart->vtab
|
|||
* @param baud_rate The baud rate to configure
|
||||
* @return the new baud rate of the UART
|
||||
*/
|
||||
inline int metal_uart_set_baud_rate(struct metal_uart *uart, int baud_rate) { return uart->vtable->set_baud_rate(uart, baud_rate); }
|
||||
__inline__ int metal_uart_set_baud_rate(struct metal_uart *uart,
|
||||
int baud_rate) {
|
||||
return uart->vtable->set_baud_rate(uart, baud_rate);
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Get the interrupt controller of the UART peripheral
|
||||
|
@ -82,13 +122,94 @@ inline int metal_uart_set_baud_rate(struct metal_uart *uart, int baud_rate) { re
|
|||
* @param uart The UART device handle
|
||||
* @return The handle for the UART interrupt controller
|
||||
*/
|
||||
inline struct metal_interrupt* metal_uart_interrupt_controller(struct metal_uart *uart) { return uart->vtable->controller_interrupt(uart); }
|
||||
__inline__ struct metal_interrupt *
|
||||
metal_uart_interrupt_controller(struct metal_uart *uart) {
|
||||
return uart->vtable->controller_interrupt(uart);
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Get the interrupt ID of the UART controller
|
||||
* @param uart The UART device handle
|
||||
* @return The UART interrupt id
|
||||
*/
|
||||
inline int metal_uart_get_interrupt_id(struct metal_uart *uart) { return uart->vtable->get_interrupt_id(uart); }
|
||||
__inline__ int metal_uart_get_interrupt_id(struct metal_uart *uart) {
|
||||
return uart->vtable->get_interrupt_id(uart);
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Enable the UART transmit interrupt
|
||||
* @param uart The UART device handle
|
||||
* @return 0 upon success
|
||||
*/
|
||||
__inline__ int metal_uart_transmit_interrupt_enable(struct metal_uart *uart) {
|
||||
return uart->vtable->tx_interrupt_enable(uart);
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Disable the UART transmit interrupt
|
||||
* @param uart The UART device handle
|
||||
* @return 0 upon success
|
||||
*/
|
||||
__inline__ int metal_uart_transmit_interrupt_disable(struct metal_uart *uart) {
|
||||
return uart->vtable->tx_interrupt_disable(uart);
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Enable the UART receive interrupt
|
||||
* @param uart The UART device handle
|
||||
* @return 0 upon success
|
||||
*/
|
||||
__inline__ int metal_uart_receive_interrupt_enable(struct metal_uart *uart) {
|
||||
return uart->vtable->rx_interrupt_enable(uart);
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Disable the UART receive interrupt
|
||||
* @param uart The UART device handle
|
||||
* @return 0 upon success
|
||||
*/
|
||||
__inline__ int metal_uart_receive_interrupt_disable(struct metal_uart *uart) {
|
||||
return uart->vtable->rx_interrupt_disable(uart);
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Set the transmit watermark level of the UART controller
|
||||
* @param uart The UART device handle
|
||||
* @param level The UART transmit watermark level
|
||||
* @return 0 upon success
|
||||
*/
|
||||
__inline__ int metal_uart_set_transmit_watermark(struct metal_uart *uart,
|
||||
size_t level) {
|
||||
return uart->vtable->set_tx_watermark(uart, level);
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Get the transmit watermark level of the UART controller
|
||||
* @param uart The UART device handle
|
||||
* @return The UART transmit watermark level
|
||||
*/
|
||||
__inline__ size_t metal_uart_get_transmit_watermark(struct metal_uart *uart) {
|
||||
return uart->vtable->get_tx_watermark(uart);
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Set the receive watermark level of the UART controller
|
||||
* @param uart The UART device handle
|
||||
* @param level The UART transmit watermark level
|
||||
* @return 0 upon success
|
||||
*/
|
||||
__inline__ int metal_uart_set_receive_watermark(struct metal_uart *uart,
|
||||
size_t level) {
|
||||
return uart->vtable->set_rx_watermark(uart, level);
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Get the receive watermark level of the UART controller
|
||||
* @param uart The UART device handle
|
||||
* @return The UART transmit watermark level
|
||||
*/
|
||||
__inline__ size_t metal_uart_get_receive_watermark(struct metal_uart *uart) {
|
||||
return uart->vtable->get_rx_watermark(uart);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -0,0 +1,168 @@
|
|||
/* Copyright 2019 SiFive, Inc */
|
||||
/* SPDX-License-Identifier: Apache-2.0 */
|
||||
|
||||
#ifndef METAL__WATCHDOG_H
|
||||
#define METAL__WATCHDOG_H
|
||||
|
||||
/*!
|
||||
* @file watchdog.h
|
||||
*
|
||||
* @brief API for configuring watchdog timers
|
||||
*/
|
||||
|
||||
#include <metal/interrupt.h>
|
||||
|
||||
struct metal_watchdog;
|
||||
|
||||
/*!
|
||||
* @brief List of watchdog timer count behaviors
|
||||
*/
|
||||
enum metal_watchdog_run_option {
|
||||
METAL_WATCHDOG_STOP = 0, /*!< Stop the watchdog */
|
||||
METAL_WATCHDOG_RUN_ALWAYS, /*!< Run the watchdog continuously, even during
|
||||
sleep */
|
||||
METAL_WATCHDOG_RUN_AWAKE, /*!< Run the watchdog only while the CPU is awake
|
||||
*/
|
||||
};
|
||||
|
||||
/*!
|
||||
* @brief List of behaviors when a watchdog triggers
|
||||
*/
|
||||
enum metal_watchdog_result {
|
||||
METAL_WATCHDOG_NO_RESULT = 0, /*!< When the watchdog triggers, do nothing */
|
||||
METAL_WATCHDOG_INTERRUPT, /*!< When the watchdog triggers, fire an interrupt
|
||||
*/
|
||||
METAL_WATCHDOG_FULL_RESET, /*!< When the watchdog triggers, cause a full
|
||||
system reset */
|
||||
};
|
||||
|
||||
struct metal_watchdog_vtable {
|
||||
int (*feed)(const struct metal_watchdog *const wdog);
|
||||
long int (*get_rate)(const struct metal_watchdog *const wdog);
|
||||
long int (*set_rate)(const struct metal_watchdog *const wdog,
|
||||
const long int rate);
|
||||
long int (*get_timeout)(const struct metal_watchdog *const wdog);
|
||||
long int (*set_timeout)(const struct metal_watchdog *const wdog,
|
||||
const long int timeout);
|
||||
int (*set_result)(const struct metal_watchdog *const wdog,
|
||||
const enum metal_watchdog_result result);
|
||||
int (*run)(const struct metal_watchdog *const wdog,
|
||||
const enum metal_watchdog_run_option option);
|
||||
struct metal_interrupt *(*get_interrupt)(
|
||||
const struct metal_watchdog *const wdog);
|
||||
int (*get_interrupt_id)(const struct metal_watchdog *const wdog);
|
||||
int (*clear_interrupt)(const struct metal_watchdog *const wdog);
|
||||
};
|
||||
|
||||
/*!
|
||||
* @brief Handle for a Watchdog Timer
|
||||
*/
|
||||
struct metal_watchdog {
|
||||
const struct metal_watchdog_vtable *vtable;
|
||||
};
|
||||
|
||||
/*!
|
||||
* @brief Feed the watchdog timer
|
||||
*/
|
||||
inline int metal_watchdog_feed(const struct metal_watchdog *const wdog) {
|
||||
return wdog->vtable->feed(wdog);
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Get the rate of the watchdog timer in Hz
|
||||
*
|
||||
* @return the rate of the watchdog timer
|
||||
*/
|
||||
inline long int
|
||||
metal_watchdog_get_rate(const struct metal_watchdog *const wdog) {
|
||||
return wdog->vtable->get_rate(wdog);
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Set the rate of the watchdog timer in Hz
|
||||
*
|
||||
* There is no guarantee that the new rate will match the requested rate.
|
||||
*
|
||||
* @return the new rate of the watchdog timer
|
||||
*/
|
||||
inline long int metal_watchdog_set_rate(const struct metal_watchdog *const wdog,
|
||||
const long int rate) {
|
||||
return wdog->vtable->set_rate(wdog, rate);
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Get the timeout of the watchdog timer
|
||||
*
|
||||
* @return the watchdog timeout value
|
||||
*/
|
||||
inline long int
|
||||
metal_watchdog_get_timeout(const struct metal_watchdog *const wdog) {
|
||||
return wdog->vtable->get_timeout(wdog);
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Set the timeout of the watchdog timer
|
||||
*
|
||||
* The set rate will be the minimimum of the requested and maximum supported
|
||||
* rates.
|
||||
*
|
||||
* @return the new watchdog timeout value
|
||||
*/
|
||||
inline long int
|
||||
metal_watchdog_set_timeout(const struct metal_watchdog *const wdog,
|
||||
const long int timeout) {
|
||||
return wdog->vtable->set_timeout(wdog, timeout);
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Sets the result behavior of a watchdog timer timeout
|
||||
*
|
||||
* @return 0 if the requested result behavior is supported
|
||||
*/
|
||||
inline int metal_watchdog_set_result(const struct metal_watchdog *const wdog,
|
||||
const enum metal_watchdog_result result) {
|
||||
return wdog->vtable->set_result(wdog, result);
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Set the run behavior of the watchdog
|
||||
*
|
||||
* Used to enable/disable the watchdog timer
|
||||
*
|
||||
* @return 0 if the watchdog was successfully started/stopped
|
||||
*/
|
||||
inline int metal_watchdog_run(const struct metal_watchdog *const wdog,
|
||||
const enum metal_watchdog_run_option option) {
|
||||
return wdog->vtable->run(wdog, option);
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Get the interrupt controller for the watchdog interrupt
|
||||
*/
|
||||
inline struct metal_interrupt *
|
||||
metal_watchdog_get_interrupt(const struct metal_watchdog *const wdog) {
|
||||
return wdog->vtable->get_interrupt(wdog);
|
||||
}
|
||||
|
||||
/*!
|
||||
* @Brief Get the interrupt id for the watchdog interrupt
|
||||
*/
|
||||
inline int
|
||||
metal_watchdog_get_interrupt_id(const struct metal_watchdog *const wdog) {
|
||||
return wdog->vtable->get_interrupt_id(wdog);
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Clear the watchdog interrupt
|
||||
*/
|
||||
inline int
|
||||
metal_watchdog_clear_interrupt(const struct metal_watchdog *const wdog) {
|
||||
return wdog->vtable->clear_interrupt(wdog);
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Get a watchdog handle
|
||||
*/
|
||||
struct metal_watchdog *metal_watchdog_get_device(const int index);
|
||||
|
||||
#endif /* METAL__WATCHDOG_H */
|
|
@ -5,128 +5,181 @@
|
|||
|
||||
#ifndef ASSEMBLY
|
||||
|
||||
#ifndef SIFIVE_HIFIVE1_REVB____METAL_INLINE_H
|
||||
#define SIFIVE_HIFIVE1_REVB____METAL_INLINE_H
|
||||
#ifndef METAL_INLINE_H
|
||||
#define METAL_INLINE_H
|
||||
|
||||
#include <metal/machine.h>
|
||||
|
||||
|
||||
/* --------------------- fixed_clock ------------ */
|
||||
extern inline unsigned long __metal_driver_fixed_clock_rate(const struct metal_clock *clock);
|
||||
extern __inline__ unsigned long __metal_driver_fixed_clock_rate(const struct metal_clock *clock);
|
||||
|
||||
|
||||
/* --------------------- fixed_factor_clock ------------ */
|
||||
|
||||
|
||||
/* --------------------- sifive_clint0 ------------ */
|
||||
extern inline unsigned long __metal_driver_sifive_clint0_control_base(struct metal_interrupt *controller);
|
||||
extern inline unsigned long __metal_driver_sifive_clint0_control_size(struct metal_interrupt *controller);
|
||||
extern inline int __metal_driver_sifive_clint0_num_interrupts(struct metal_interrupt *controller);
|
||||
extern inline struct metal_interrupt * __metal_driver_sifive_clint0_interrupt_parents(struct metal_interrupt *controller, int idx);
|
||||
extern inline int __metal_driver_sifive_clint0_interrupt_lines(struct metal_interrupt *controller, int idx);
|
||||
extern __inline__ unsigned long __metal_driver_sifive_clint0_control_base(struct metal_interrupt *controller);
|
||||
extern __inline__ unsigned long __metal_driver_sifive_clint0_control_size(struct metal_interrupt *controller);
|
||||
extern __inline__ int __metal_driver_sifive_clint0_num_interrupts(struct metal_interrupt *controller);
|
||||
extern __inline__ struct metal_interrupt * __metal_driver_sifive_clint0_interrupt_parents(struct metal_interrupt *controller, int idx);
|
||||
extern __inline__ int __metal_driver_sifive_clint0_interrupt_lines(struct metal_interrupt *controller, int idx);
|
||||
|
||||
|
||||
/* --------------------- cpu ------------ */
|
||||
extern inline int __metal_driver_cpu_hartid(struct metal_cpu *cpu);
|
||||
extern inline int __metal_driver_cpu_timebase(struct metal_cpu *cpu);
|
||||
extern inline struct metal_interrupt * __metal_driver_cpu_interrupt_controller(struct metal_cpu *cpu);
|
||||
extern inline int __metal_driver_cpu_num_pmp_regions(struct metal_cpu *cpu);
|
||||
extern __inline__ int __metal_driver_cpu_hartid(struct metal_cpu *cpu);
|
||||
extern __inline__ int __metal_driver_cpu_timebase(struct metal_cpu *cpu);
|
||||
extern __inline__ struct metal_interrupt * __metal_driver_cpu_interrupt_controller(struct metal_cpu *cpu);
|
||||
extern __inline__ int __metal_driver_cpu_num_pmp_regions(struct metal_cpu *cpu);
|
||||
extern __inline__ struct metal_buserror * __metal_driver_cpu_buserror(struct metal_cpu *cpu);
|
||||
|
||||
|
||||
/* --------------------- sifive_plic0 ------------ */
|
||||
extern inline unsigned long __metal_driver_sifive_plic0_control_base(struct metal_interrupt *controller);
|
||||
extern inline unsigned long __metal_driver_sifive_plic0_control_size(struct metal_interrupt *controller);
|
||||
extern inline int __metal_driver_sifive_plic0_num_interrupts(struct metal_interrupt *controller);
|
||||
extern inline int __metal_driver_sifive_plic0_max_priority(struct metal_interrupt *controller);
|
||||
extern inline struct metal_interrupt * __metal_driver_sifive_plic0_interrupt_parents(struct metal_interrupt *controller, int idx);
|
||||
extern inline int __metal_driver_sifive_plic0_interrupt_lines(struct metal_interrupt *controller, int idx);
|
||||
extern __inline__ unsigned long __metal_driver_sifive_plic0_control_base(struct metal_interrupt *controller);
|
||||
extern __inline__ unsigned long __metal_driver_sifive_plic0_control_size(struct metal_interrupt *controller);
|
||||
extern __inline__ int __metal_driver_sifive_plic0_num_interrupts(struct metal_interrupt *controller);
|
||||
extern __inline__ int __metal_driver_sifive_plic0_max_priority(struct metal_interrupt *controller);
|
||||
extern __inline__ struct metal_interrupt * __metal_driver_sifive_plic0_interrupt_parents(struct metal_interrupt *controller, int idx);
|
||||
extern __inline__ int __metal_driver_sifive_plic0_interrupt_lines(struct metal_interrupt *controller, int idx);
|
||||
extern __inline__ int __metal_driver_sifive_plic0_context_ids(int hartid);
|
||||
|
||||
|
||||
/* --------------------- sifive_buserror0 ------------ */
|
||||
|
||||
|
||||
/* --------------------- sifive_clic0 ------------ */
|
||||
|
||||
|
||||
/* --------------------- sifive_local_external_interrupts0 ------------ */
|
||||
extern inline struct metal_interrupt * __metal_driver_sifive_local_external_interrupts0_interrupt_parent(struct metal_interrupt *controller);
|
||||
extern inline int __metal_driver_sifive_local_external_interrupts0_num_interrupts(struct metal_interrupt *controller);
|
||||
extern inline int __metal_driver_sifive_local_external_interrupts0_interrupt_lines(struct metal_interrupt *controller, int idx);
|
||||
|
||||
|
||||
/* --------------------- sifive_global_external_interrupts0 ------------ */
|
||||
|
||||
|
||||
/* --------------------- sifive_gpio0 ------------ */
|
||||
extern inline unsigned long __metal_driver_sifive_gpio0_base(struct metal_gpio *gpio);
|
||||
extern inline unsigned long __metal_driver_sifive_gpio0_size(struct metal_gpio *gpio);
|
||||
extern inline int __metal_driver_sifive_gpio0_num_interrupts(struct metal_gpio *gpio);
|
||||
extern inline struct metal_interrupt * __metal_driver_sifive_gpio0_interrupt_parent(struct metal_gpio *gpio);
|
||||
extern inline int __metal_driver_sifive_gpio0_interrupt_lines(struct metal_gpio *gpio, int idx);
|
||||
extern __inline__ unsigned long __metal_driver_sifive_gpio0_base(struct metal_gpio *gpio);
|
||||
extern __inline__ unsigned long __metal_driver_sifive_gpio0_size(struct metal_gpio *gpio);
|
||||
extern __inline__ int __metal_driver_sifive_gpio0_num_interrupts(struct metal_gpio *gpio);
|
||||
extern __inline__ struct metal_interrupt * __metal_driver_sifive_gpio0_interrupt_parent(struct metal_gpio *gpio);
|
||||
extern __inline__ int __metal_driver_sifive_gpio0_interrupt_lines(struct metal_gpio *gpio, int idx);
|
||||
|
||||
|
||||
/* --------------------- sifive_gpio_button ------------ */
|
||||
|
||||
|
||||
/* --------------------- sifive_gpio_led ------------ */
|
||||
extern inline struct metal_gpio * __metal_driver_sifive_gpio_led_gpio(struct metal_led *led);
|
||||
extern inline int __metal_driver_sifive_gpio_led_pin(struct metal_led *led);
|
||||
extern inline char * __metal_driver_sifive_gpio_led_label(struct metal_led *led);
|
||||
extern __inline__ struct metal_gpio * __metal_driver_sifive_gpio_led_gpio(struct metal_led *led);
|
||||
extern __inline__ int __metal_driver_sifive_gpio_led_pin(struct metal_led *led);
|
||||
extern __inline__ char * __metal_driver_sifive_gpio_led_label(struct metal_led *led);
|
||||
|
||||
|
||||
/* --------------------- sifive_gpio_switch ------------ */
|
||||
|
||||
|
||||
/* --------------------- sifive_i2c0 ------------ */
|
||||
extern __inline__ unsigned long __metal_driver_sifive_i2c0_control_base(struct metal_i2c *i2c);
|
||||
extern __inline__ unsigned long __metal_driver_sifive_i2c0_control_size(struct metal_i2c *i2c);
|
||||
extern __inline__ int __metal_driver_sifive_i2c0_num_interrupts(struct metal_i2c *i2c);
|
||||
extern __inline__ struct metal_interrupt * __metal_driver_sifive_i2c0_interrupt_parent(struct metal_i2c *i2c);
|
||||
extern __inline__ int __metal_driver_sifive_i2c0_interrupt_line(struct metal_i2c *i2c);
|
||||
extern __inline__ struct metal_clock * __metal_driver_sifive_i2c0_clock(struct metal_i2c *i2c);
|
||||
extern __inline__ struct __metal_driver_sifive_gpio0 * __metal_driver_sifive_i2c0_pinmux(struct metal_i2c *i2c);
|
||||
extern __inline__ unsigned long __metal_driver_sifive_i2c0_pinmux_output_selector(struct metal_i2c *i2c);
|
||||
extern __inline__ unsigned long __metal_driver_sifive_i2c0_pinmux_source_selector(struct metal_i2c *i2c);
|
||||
|
||||
|
||||
/* --------------------- sifive_pwm0 ------------ */
|
||||
extern __inline__ unsigned long __metal_driver_sifive_pwm0_control_base(struct metal_pwm *pwm);
|
||||
extern __inline__ unsigned long __metal_driver_sifive_pwm0_control_size(struct metal_pwm *pwm);
|
||||
extern __inline__ int __metal_driver_sifive_pwm0_num_interrupts(struct metal_pwm *pwm);
|
||||
extern __inline__ struct metal_interrupt * __metal_driver_sifive_pwm0_interrupt_parent(struct metal_pwm *pwm);
|
||||
extern __inline__ int __metal_driver_sifive_pwm0_interrupt_lines(struct metal_pwm *pwm, int idx);
|
||||
extern __inline__ struct metal_clock * __metal_driver_sifive_pwm0_clock(struct metal_pwm *pwm);
|
||||
extern __inline__ struct __metal_driver_sifive_gpio0 * __metal_driver_sifive_pwm0_pinmux(struct metal_pwm *pwm);
|
||||
extern __inline__ unsigned long __metal_driver_sifive_pwm0_pinmux_output_selector(struct metal_pwm *pwm);
|
||||
extern __inline__ unsigned long __metal_driver_sifive_pwm0_pinmux_source_selector(struct metal_pwm *pwm);
|
||||
extern __inline__ int __metal_driver_sifive_pwm0_compare_width(struct metal_pwm *pwm);
|
||||
extern __inline__ int __metal_driver_sifive_pwm0_comparator_count(struct metal_pwm *pwm);
|
||||
|
||||
|
||||
/* --------------------- sifive_rtc0 ------------ */
|
||||
extern __inline__ unsigned long __metal_driver_sifive_rtc0_control_base(const struct metal_rtc *const rtc);
|
||||
extern __inline__ unsigned long __metal_driver_sifive_rtc0_control_size(const struct metal_rtc *const rtc);
|
||||
extern __inline__ struct metal_interrupt * __metal_driver_sifive_rtc0_interrupt_parent(const struct metal_rtc *const rtc);
|
||||
extern __inline__ int __metal_driver_sifive_rtc0_interrupt_line(const struct metal_rtc *const rtc);
|
||||
extern __inline__ struct metal_clock * __metal_driver_sifive_rtc0_clock(const struct metal_rtc *const rtc);
|
||||
|
||||
|
||||
/* --------------------- sifive_spi0 ------------ */
|
||||
extern inline unsigned long __metal_driver_sifive_spi0_control_base(struct metal_spi *spi);
|
||||
extern inline unsigned long __metal_driver_sifive_spi0_control_size(struct metal_spi *spi);
|
||||
extern inline struct __metal_driver_sifive_gpio0 * __metal_driver_sifive_spi0_pinmux(struct metal_spi *spi);
|
||||
extern inline unsigned long __metal_driver_sifive_spi0_pinmux_output_selector(struct metal_spi *spi);
|
||||
extern inline unsigned long __metal_driver_sifive_spi0_pinmux_source_selector(struct metal_spi *spi);
|
||||
extern __inline__ unsigned long __metal_driver_sifive_spi0_control_base(struct metal_spi *spi);
|
||||
extern __inline__ unsigned long __metal_driver_sifive_spi0_control_size(struct metal_spi *spi);
|
||||
extern __inline__ struct __metal_driver_sifive_gpio0 * __metal_driver_sifive_spi0_pinmux(struct metal_spi *spi);
|
||||
extern __inline__ unsigned long __metal_driver_sifive_spi0_pinmux_output_selector(struct metal_spi *spi);
|
||||
extern __inline__ unsigned long __metal_driver_sifive_spi0_pinmux_source_selector(struct metal_spi *spi);
|
||||
|
||||
|
||||
/* --------------------- sifive_test0 ------------ */
|
||||
|
||||
|
||||
/* --------------------- sifive_trace ------------ */
|
||||
|
||||
/* --------------------- sifive_uart0 ------------ */
|
||||
extern inline unsigned long __metal_driver_sifive_uart0_control_base(struct metal_uart *uart);
|
||||
extern inline unsigned long __metal_driver_sifive_uart0_control_size(struct metal_uart *uart);
|
||||
extern inline int __metal_driver_sifive_uart0_num_interrupts(struct metal_uart *uart);
|
||||
extern inline struct metal_interrupt * __metal_driver_sifive_uart0_interrupt_parent(struct metal_uart *uart);
|
||||
extern inline int __metal_driver_sifive_uart0_interrupt_line(struct metal_uart *uart);
|
||||
extern inline struct metal_clock * __metal_driver_sifive_uart0_clock(struct metal_uart *uart);
|
||||
extern inline struct __metal_driver_sifive_gpio0 * __metal_driver_sifive_uart0_pinmux(struct metal_uart *uart);
|
||||
extern inline unsigned long __metal_driver_sifive_uart0_pinmux_output_selector(struct metal_uart *uart);
|
||||
extern inline unsigned long __metal_driver_sifive_uart0_pinmux_source_selector(struct metal_uart *uart);
|
||||
extern __inline__ unsigned long __metal_driver_sifive_uart0_control_base(struct metal_uart *uart);
|
||||
extern __inline__ unsigned long __metal_driver_sifive_uart0_control_size(struct metal_uart *uart);
|
||||
extern __inline__ int __metal_driver_sifive_uart0_num_interrupts(struct metal_uart *uart);
|
||||
extern __inline__ struct metal_interrupt * __metal_driver_sifive_uart0_interrupt_parent(struct metal_uart *uart);
|
||||
extern __inline__ int __metal_driver_sifive_uart0_interrupt_line(struct metal_uart *uart);
|
||||
extern __inline__ struct metal_clock * __metal_driver_sifive_uart0_clock(struct metal_uart *uart);
|
||||
extern __inline__ struct __metal_driver_sifive_gpio0 * __metal_driver_sifive_uart0_pinmux(struct metal_uart *uart);
|
||||
extern __inline__ unsigned long __metal_driver_sifive_uart0_pinmux_output_selector(struct metal_uart *uart);
|
||||
extern __inline__ unsigned long __metal_driver_sifive_uart0_pinmux_source_selector(struct metal_uart *uart);
|
||||
|
||||
|
||||
/* --------------------- sifive_simuart0 ------------ */
|
||||
|
||||
|
||||
/* --------------------- sifive_wdog0 ------------ */
|
||||
extern __inline__ unsigned long __metal_driver_sifive_wdog0_control_base(const struct metal_watchdog *const watchdog);
|
||||
extern __inline__ unsigned long __metal_driver_sifive_wdog0_control_size(const struct metal_watchdog *const watchdog);
|
||||
extern __inline__ struct metal_interrupt * __metal_driver_sifive_wdog0_interrupt_parent(const struct metal_watchdog *const watchdog);
|
||||
extern __inline__ int __metal_driver_sifive_wdog0_interrupt_line(const struct metal_watchdog *const watchdog);
|
||||
extern __inline__ struct metal_clock * __metal_driver_sifive_wdog0_clock(const struct metal_watchdog *const watchdog);
|
||||
|
||||
|
||||
/* --------------------- sifive_fe310_g000_hfrosc ------------ */
|
||||
extern inline struct metal_clock * __metal_driver_sifive_fe310_g000_hfrosc_ref(const struct metal_clock *clock);
|
||||
extern inline struct __metal_driver_sifive_fe310_g000_prci * __metal_driver_sifive_fe310_g000_hfrosc_config_base(const struct metal_clock *clock);
|
||||
extern inline const struct __metal_driver_vtable_sifive_fe310_g000_prci * __metal_driver_sifive_fe310_g000_hfrosc_config_vtable(struct metal_clock *clock);
|
||||
extern inline long __metal_driver_sifive_fe310_g000_hfrosc_config_offset(const struct metal_clock *clock);
|
||||
extern __inline__ struct metal_clock * __metal_driver_sifive_fe310_g000_hfrosc_ref(const struct metal_clock *clock);
|
||||
extern __inline__ struct __metal_driver_sifive_fe310_g000_prci * __metal_driver_sifive_fe310_g000_hfrosc_config_base(const struct metal_clock *clock);
|
||||
extern __inline__ const struct __metal_driver_vtable_sifive_fe310_g000_prci * __metal_driver_sifive_fe310_g000_hfrosc_config_vtable(struct metal_clock *clock);
|
||||
extern __inline__ long __metal_driver_sifive_fe310_g000_hfrosc_config_offset(const struct metal_clock *clock);
|
||||
|
||||
|
||||
/* --------------------- sifive_fe310_g000_hfxosc ------------ */
|
||||
extern inline struct metal_clock * __metal_driver_sifive_fe310_g000_hfxosc_ref(const struct metal_clock *clock);
|
||||
extern inline struct __metal_driver_sifive_fe310_g000_prci * __metal_driver_sifive_fe310_g000_hfxosc_config_base(const struct metal_clock *clock);
|
||||
extern inline long __metal_driver_sifive_fe310_g000_hfxosc_config_offset(const struct metal_clock *clock);
|
||||
extern __inline__ struct metal_clock * __metal_driver_sifive_fe310_g000_hfxosc_ref(const struct metal_clock *clock);
|
||||
extern __inline__ struct __metal_driver_sifive_fe310_g000_prci * __metal_driver_sifive_fe310_g000_hfxosc_config_base(const struct metal_clock *clock);
|
||||
extern __inline__ long __metal_driver_sifive_fe310_g000_hfxosc_config_offset(const struct metal_clock *clock);
|
||||
|
||||
|
||||
/* --------------------- sifive_fe310_g000_lfrosc ------------ */
|
||||
extern __inline__ struct metal_clock * __metal_driver_sifive_fe310_g000_lfrosc_lfrosc(const struct metal_clock *clock);
|
||||
extern __inline__ struct metal_clock * __metal_driver_sifive_fe310_g000_lfrosc_psdlfaltclk(const struct metal_clock *clock);
|
||||
extern __inline__ unsigned long int __metal_driver_sifive_fe310_g000_lfrosc_config_reg(const struct metal_clock *clock);
|
||||
extern __inline__ unsigned long int __metal_driver_sifive_fe310_g000_lfrosc_mux_reg(const struct metal_clock *clock);
|
||||
|
||||
|
||||
/* --------------------- sifive_fe310_g000_pll ------------ */
|
||||
extern inline struct metal_clock * __metal_driver_sifive_fe310_g000_pll_pllsel0(const struct metal_clock *clock);
|
||||
extern inline struct metal_clock * __metal_driver_sifive_fe310_g000_pll_pllref(const struct metal_clock *clock);
|
||||
extern inline struct __metal_driver_sifive_fe310_g000_prci * __metal_driver_sifive_fe310_g000_pll_config_base( );
|
||||
extern inline long __metal_driver_sifive_fe310_g000_pll_config_offset( );
|
||||
extern inline struct __metal_driver_sifive_fe310_g000_prci * __metal_driver_sifive_fe310_g000_pll_divider_base(const struct metal_clock *clock);
|
||||
extern inline long __metal_driver_sifive_fe310_g000_pll_divider_offset(const struct metal_clock *clock);
|
||||
extern inline long __metal_driver_sifive_fe310_g000_pll_init_rate( );
|
||||
extern __inline__ struct metal_clock * __metal_driver_sifive_fe310_g000_pll_pllsel0(const struct metal_clock *clock);
|
||||
extern __inline__ struct metal_clock * __metal_driver_sifive_fe310_g000_pll_pllref(const struct metal_clock *clock);
|
||||
extern __inline__ struct __metal_driver_sifive_fe310_g000_prci * __metal_driver_sifive_fe310_g000_pll_config_base( );
|
||||
extern __inline__ long __metal_driver_sifive_fe310_g000_pll_config_offset( );
|
||||
extern __inline__ struct __metal_driver_sifive_fe310_g000_prci * __metal_driver_sifive_fe310_g000_pll_divider_base(const struct metal_clock *clock);
|
||||
extern __inline__ long __metal_driver_sifive_fe310_g000_pll_divider_offset(const struct metal_clock *clock);
|
||||
extern __inline__ long __metal_driver_sifive_fe310_g000_pll_init_rate( );
|
||||
|
||||
|
||||
/* --------------------- fe310_g000_prci ------------ */
|
||||
extern inline long __metal_driver_sifive_fe310_g000_prci_base( );
|
||||
extern inline long __metal_driver_sifive_fe310_g000_prci_size( );
|
||||
extern inline const struct __metal_driver_vtable_sifive_fe310_g000_prci * __metal_driver_sifive_fe310_g000_prci_vtable( );
|
||||
|
||||
|
||||
/* --------------------- sifive_fu540_c000_l2 ------------ */
|
||||
extern __inline__ long __metal_driver_sifive_fe310_g000_prci_base( );
|
||||
extern __inline__ long __metal_driver_sifive_fe310_g000_prci_size( );
|
||||
extern __inline__ const struct __metal_driver_vtable_sifive_fe310_g000_prci * __metal_driver_sifive_fe310_g000_prci_vtable( );
|
||||
|
||||
|
||||
/* From clock@0 */
|
||||
|
@ -144,6 +197,11 @@ struct __metal_driver_fixed_clock __metal_dt_clock_5 = {
|
|||
.clock.vtable = &__metal_driver_vtable_fixed_clock.clock,
|
||||
};
|
||||
|
||||
/* From clock@6 */
|
||||
struct __metal_driver_fixed_clock __metal_dt_clock_6 = {
|
||||
.clock.vtable = &__metal_driver_vtable_fixed_clock.clock,
|
||||
};
|
||||
|
||||
struct metal_memory __metal_dt_mem_dtim_80000000 = {
|
||||
._base_address = 2147483648UL,
|
||||
._size = 16384UL,
|
||||
|
@ -155,6 +213,17 @@ struct metal_memory __metal_dt_mem_dtim_80000000 = {
|
|||
.A = 1},
|
||||
};
|
||||
|
||||
struct metal_memory __metal_dt_mem_itim_8000000 = {
|
||||
._base_address = 134217728UL,
|
||||
._size = 8192UL,
|
||||
._attrs = {
|
||||
.R = 1,
|
||||
.W = 1,
|
||||
.X = 1,
|
||||
.C = 1,
|
||||
.A = 1},
|
||||
};
|
||||
|
||||
struct metal_memory __metal_dt_mem_spi_10014000 = {
|
||||
._base_address = 536870912UL,
|
||||
._size = 500000UL,
|
||||
|
@ -166,6 +235,24 @@ struct metal_memory __metal_dt_mem_spi_10014000 = {
|
|||
.A = 1},
|
||||
};
|
||||
|
||||
struct metal_memory __metal_dt_mem_spi_10024000 = {
|
||||
._attrs = {
|
||||
.R = 1,
|
||||
.W = 1,
|
||||
.X = 1,
|
||||
.C = 1,
|
||||
.A = 1},
|
||||
};
|
||||
|
||||
struct metal_memory __metal_dt_mem_spi_10034000 = {
|
||||
._attrs = {
|
||||
.R = 1,
|
||||
.W = 1,
|
||||
.X = 1,
|
||||
.C = 1,
|
||||
.A = 1},
|
||||
};
|
||||
|
||||
/* From clint@2000000 */
|
||||
struct __metal_driver_riscv_clint0 __metal_dt_clint_2000000 = {
|
||||
.controller.vtable = &__metal_driver_vtable_riscv_clint0.clint_vtable,
|
||||
|
@ -175,6 +262,7 @@ struct __metal_driver_riscv_clint0 __metal_dt_clint_2000000 = {
|
|||
/* From cpu@0 */
|
||||
struct __metal_driver_cpu __metal_dt_cpu_0 = {
|
||||
.cpu.vtable = &__metal_driver_vtable_cpu.cpu_vtable,
|
||||
.hpm_count = 0,
|
||||
};
|
||||
|
||||
/* From interrupt_controller */
|
||||
|
@ -189,42 +277,83 @@ struct __metal_driver_riscv_plic0 __metal_dt_interrupt_controller_c000000 = {
|
|||
.init_done = 0,
|
||||
};
|
||||
|
||||
/* From local_external_interrupts_0 */
|
||||
struct __metal_driver_sifive_local_external_interrupts0 __metal_dt_local_external_interrupts_0 = {
|
||||
.irc.vtable = &__metal_driver_vtable_sifive_local_external_interrupts0.local0_vtable,
|
||||
.init_done = 0,
|
||||
};
|
||||
struct metal_pmp __metal_dt_pmp;
|
||||
|
||||
/* From gpio@10012000 */
|
||||
struct __metal_driver_sifive_gpio0 __metal_dt_gpio_10012000 = {
|
||||
.gpio.vtable = &__metal_driver_vtable_sifive_gpio0.gpio,
|
||||
};
|
||||
|
||||
/* From led@0red */
|
||||
struct __metal_driver_sifive_gpio_led __metal_dt_led_0red = {
|
||||
/* From led@0 */
|
||||
struct __metal_driver_sifive_gpio_led __metal_dt_led_0 = {
|
||||
.led.vtable = &__metal_driver_vtable_sifive_led.led_vtable,
|
||||
};
|
||||
|
||||
/* From led@0green */
|
||||
struct __metal_driver_sifive_gpio_led __metal_dt_led_0green = {
|
||||
/* From led@1 */
|
||||
struct __metal_driver_sifive_gpio_led __metal_dt_led_1 = {
|
||||
.led.vtable = &__metal_driver_vtable_sifive_led.led_vtable,
|
||||
};
|
||||
|
||||
/* From led@0blue */
|
||||
struct __metal_driver_sifive_gpio_led __metal_dt_led_0blue = {
|
||||
/* From led@2 */
|
||||
struct __metal_driver_sifive_gpio_led __metal_dt_led_2 = {
|
||||
.led.vtable = &__metal_driver_vtable_sifive_led.led_vtable,
|
||||
};
|
||||
|
||||
/* From i2c@10016000 */
|
||||
struct __metal_driver_sifive_i2c0 __metal_dt_i2c_10016000 = {
|
||||
.i2c.vtable = &__metal_driver_vtable_sifive_i2c0.i2c,
|
||||
};
|
||||
|
||||
/* From pwm@10015000 */
|
||||
struct __metal_driver_sifive_pwm0 __metal_dt_pwm_10015000 = {
|
||||
.pwm.vtable = &__metal_driver_vtable_sifive_pwm0.pwm,
|
||||
};
|
||||
|
||||
/* From pwm@10025000 */
|
||||
struct __metal_driver_sifive_pwm0 __metal_dt_pwm_10025000 = {
|
||||
.pwm.vtable = &__metal_driver_vtable_sifive_pwm0.pwm,
|
||||
};
|
||||
|
||||
/* From pwm@10035000 */
|
||||
struct __metal_driver_sifive_pwm0 __metal_dt_pwm_10035000 = {
|
||||
.pwm.vtable = &__metal_driver_vtable_sifive_pwm0.pwm,
|
||||
};
|
||||
|
||||
/* From aon@10000000 */
|
||||
struct __metal_driver_sifive_rtc0 __metal_dt_rtc_10000000 = {
|
||||
.rtc.vtable = &__metal_driver_vtable_sifive_rtc0.rtc,
|
||||
};
|
||||
|
||||
/* From spi@10014000 */
|
||||
struct __metal_driver_sifive_spi0 __metal_dt_spi_10014000 = {
|
||||
.spi.vtable = &__metal_driver_vtable_sifive_spi0.spi,
|
||||
};
|
||||
|
||||
/* From spi@10024000 */
|
||||
struct __metal_driver_sifive_spi0 __metal_dt_spi_10024000 = {
|
||||
.spi.vtable = &__metal_driver_vtable_sifive_spi0.spi,
|
||||
};
|
||||
|
||||
/* From spi@10034000 */
|
||||
struct __metal_driver_sifive_spi0 __metal_dt_spi_10034000 = {
|
||||
.spi.vtable = &__metal_driver_vtable_sifive_spi0.spi,
|
||||
};
|
||||
|
||||
/* From serial@10013000 */
|
||||
struct __metal_driver_sifive_uart0 __metal_dt_serial_10013000 = {
|
||||
.uart.vtable = &__metal_driver_vtable_sifive_uart0.uart,
|
||||
};
|
||||
|
||||
/* From serial@10023000 */
|
||||
struct __metal_driver_sifive_uart0 __metal_dt_serial_10023000 = {
|
||||
.uart.vtable = &__metal_driver_vtable_sifive_uart0.uart,
|
||||
};
|
||||
|
||||
/* From aon@10000000 */
|
||||
struct __metal_driver_sifive_wdog0 __metal_dt_aon_10000000 = {
|
||||
.watchdog.vtable = &__metal_driver_vtable_sifive_wdog0.watchdog,
|
||||
};
|
||||
|
||||
/* From clock@3 */
|
||||
struct __metal_driver_sifive_fe310_g000_hfrosc __metal_dt_clock_3 = {
|
||||
.clock.vtable = &__metal_driver_vtable_sifive_fe310_g000_hfrosc.clock,
|
||||
|
@ -235,6 +364,11 @@ struct __metal_driver_sifive_fe310_g000_hfxosc __metal_dt_clock_1 = {
|
|||
.clock.vtable = &__metal_driver_vtable_sifive_fe310_g000_hfxosc.clock,
|
||||
};
|
||||
|
||||
/* From clock@7 */
|
||||
struct __metal_driver_sifive_fe310_g000_lfrosc __metal_dt_clock_7 = {
|
||||
.clock.vtable = &__metal_driver_vtable_sifive_fe310_g000_lfrosc.clock,
|
||||
};
|
||||
|
||||
/* From clock@4 */
|
||||
struct __metal_driver_sifive_fe310_g000_pll __metal_dt_clock_4 = {
|
||||
.clock.vtable = &__metal_driver_vtable_sifive_fe310_g000_pll.clock,
|
||||
|
@ -242,8 +376,9 @@ struct __metal_driver_sifive_fe310_g000_pll __metal_dt_clock_4 = {
|
|||
|
||||
/* From prci@10008000 */
|
||||
struct __metal_driver_sifive_fe310_g000_prci __metal_dt_prci_10008000 = {
|
||||
.vtable = &__metal_driver_vtable_sifive_fe310_g000_prci,
|
||||
};
|
||||
|
||||
|
||||
#endif /* SIFIVE_HIFIVE1_REVB____METAL_INLINE_H*/
|
||||
#endif /* METAL_INLINE_H*/
|
||||
#endif /* ! ASSEMBLY */
|
||||
|
|
|
@ -3,8 +3,8 @@
|
|||
/* ----------------------------------- */
|
||||
/* ----------------------------------- */
|
||||
|
||||
#ifndef SIFIVE_HIFIVE1_REVB____METAL_PLATFORM_H
|
||||
#define SIFIVE_HIFIVE1_REVB____METAL_PLATFORM_H
|
||||
#ifndef METAL_PLATFORM_H
|
||||
#define METAL_PLATFORM_H
|
||||
|
||||
/* From clock@0 */
|
||||
#define METAL_FIXED_CLOCK_0_CLOCK_FREQUENCY 16000000UL
|
||||
|
@ -13,7 +13,10 @@
|
|||
#define METAL_FIXED_CLOCK_2_CLOCK_FREQUENCY 72000000UL
|
||||
|
||||
/* From clock@5 */
|
||||
#define METAL_FIXED_CLOCK_5_CLOCK_FREQUENCY 32000000UL
|
||||
#define METAL_FIXED_CLOCK_5_CLOCK_FREQUENCY 32768UL
|
||||
|
||||
/* From clock@6 */
|
||||
#define METAL_FIXED_CLOCK_6_CLOCK_FREQUENCY 32768UL
|
||||
|
||||
#define METAL_FIXED_CLOCK
|
||||
|
||||
|
@ -35,15 +38,18 @@
|
|||
#define METAL_RISCV_PLIC0_0_SIZE 67108864UL
|
||||
#define METAL_RISCV_PLIC0_C000000_RISCV_MAX_PRIORITY 7UL
|
||||
#define METAL_RISCV_PLIC0_0_RISCV_MAX_PRIORITY 7UL
|
||||
#define METAL_RISCV_PLIC0_C000000_RISCV_NDEV 27UL
|
||||
#define METAL_RISCV_PLIC0_0_RISCV_NDEV 27UL
|
||||
#define METAL_RISCV_PLIC0_C000000_RISCV_NDEV 53UL
|
||||
#define METAL_RISCV_PLIC0_0_RISCV_NDEV 53UL
|
||||
|
||||
#define METAL_RISCV_PLIC0
|
||||
#define METAL_RISCV_PLIC0_PRIORITY_BASE 0UL
|
||||
#define METAL_RISCV_PLIC0_PENDING_BASE 4096UL
|
||||
#define METAL_RISCV_PLIC0_ENABLE_BASE 8192UL
|
||||
#define METAL_RISCV_PLIC0_THRESHOLD 2097152UL
|
||||
#define METAL_RISCV_PLIC0_CLAIM 2097156UL
|
||||
#define METAL_RISCV_PLIC0_ENABLE_PER_HART 128UL
|
||||
#define METAL_RISCV_PLIC0_CONTEXT_BASE 2097152UL
|
||||
#define METAL_RISCV_PLIC0_CONTEXT_PER_HART 4096UL
|
||||
#define METAL_RISCV_PLIC0_CONTEXT_THRESHOLD 0UL
|
||||
#define METAL_RISCV_PLIC0_CONTEXT_CLAIM 4UL
|
||||
|
||||
/* From aon@10000000 */
|
||||
#define METAL_SIFIVE_AON0_10000000_BASE_ADDRESS 268435456UL
|
||||
|
@ -111,6 +117,10 @@
|
|||
|
||||
#define METAL_SIFIVE_FE310_G000_HFXOSC
|
||||
|
||||
/* From clock@7 */
|
||||
|
||||
#define METAL_SIFIVE_FE310_G000_LFROSC
|
||||
|
||||
/* From prci@10008000 */
|
||||
#define METAL_SIFIVE_FE310_G000_PRCI_10008000_BASE_ADDRESS 268468224UL
|
||||
#define METAL_SIFIVE_FE310_G000_PRCI_0_BASE_ADDRESS 268468224UL
|
||||
|
@ -153,11 +163,11 @@
|
|||
#define METAL_SIFIVE_GPIO0_IOF_SEL 60UL
|
||||
#define METAL_SIFIVE_GPIO0_OUT_XOR 64UL
|
||||
|
||||
/* From led@0red */
|
||||
/* From led@0 */
|
||||
|
||||
/* From led@0green */
|
||||
/* From led@1 */
|
||||
|
||||
/* From led@0blue */
|
||||
/* From led@2 */
|
||||
|
||||
#define METAL_SIFIVE_GPIO_LEDS
|
||||
|
||||
|
@ -176,16 +186,24 @@
|
|||
#define METAL_SIFIVE_I2C0_COMMAND 16UL
|
||||
#define METAL_SIFIVE_I2C0_STATUS 16UL
|
||||
|
||||
/* From local_external_interrupts_0 */
|
||||
|
||||
#define METAL_SIFIVE_LOCAL_EXTERNAL_INTERRUPTS0
|
||||
|
||||
/* From pwm@10015000 */
|
||||
#define METAL_SIFIVE_PWM0_10015000_BASE_ADDRESS 268521472UL
|
||||
#define METAL_SIFIVE_PWM0_0_BASE_ADDRESS 268521472UL
|
||||
#define METAL_SIFIVE_PWM0_10015000_SIZE 4096UL
|
||||
#define METAL_SIFIVE_PWM0_0_SIZE 4096UL
|
||||
|
||||
/* From pwm@10025000 */
|
||||
#define METAL_SIFIVE_PWM0_10025000_BASE_ADDRESS 268587008UL
|
||||
#define METAL_SIFIVE_PWM0_1_BASE_ADDRESS 268587008UL
|
||||
#define METAL_SIFIVE_PWM0_10025000_SIZE 4096UL
|
||||
#define METAL_SIFIVE_PWM0_1_SIZE 4096UL
|
||||
|
||||
/* From pwm@10035000 */
|
||||
#define METAL_SIFIVE_PWM0_10035000_BASE_ADDRESS 268652544UL
|
||||
#define METAL_SIFIVE_PWM0_2_BASE_ADDRESS 268652544UL
|
||||
#define METAL_SIFIVE_PWM0_10035000_SIZE 4096UL
|
||||
#define METAL_SIFIVE_PWM0_2_SIZE 4096UL
|
||||
|
||||
#define METAL_SIFIVE_PWM0
|
||||
#define METAL_SIFIVE_PWM0_PWMCFG 0UL
|
||||
#define METAL_SIFIVE_PWM0_PWMCOUNT 8UL
|
||||
|
@ -195,12 +213,37 @@
|
|||
#define METAL_SIFIVE_PWM0_PWMCMP2 40UL
|
||||
#define METAL_SIFIVE_PWM0_PWMCMP3 44UL
|
||||
|
||||
/* From aon@10000000 */
|
||||
#define METAL_SIFIVE_AON0_10000000_BASE_ADDRESS 268435456UL
|
||||
#define METAL_SIFIVE_AON0_0_BASE_ADDRESS 268435456UL
|
||||
#define METAL_SIFIVE_AON0_10000000_SIZE 32768UL
|
||||
#define METAL_SIFIVE_AON0_0_SIZE 32768UL
|
||||
|
||||
#define METAL_SIFIVE_RTC0
|
||||
#define METAL_SIFIVE_RTC0_RTCCFG 64UL
|
||||
#define METAL_SIFIVE_RTC0_RTCCOUNTLO 72UL
|
||||
#define METAL_SIFIVE_RTC0_RTCCOUNTHI 76UL
|
||||
#define METAL_SIFIVE_RTC0_RTCS 80UL
|
||||
#define METAL_SIFIVE_RTC0_RTCCMP0 96UL
|
||||
|
||||
/* From spi@10014000 */
|
||||
#define METAL_SIFIVE_SPI0_10014000_BASE_ADDRESS 268517376UL
|
||||
#define METAL_SIFIVE_SPI0_0_BASE_ADDRESS 268517376UL
|
||||
#define METAL_SIFIVE_SPI0_10014000_SIZE 4096UL
|
||||
#define METAL_SIFIVE_SPI0_0_SIZE 4096UL
|
||||
|
||||
/* From spi@10024000 */
|
||||
#define METAL_SIFIVE_SPI0_10024000_BASE_ADDRESS 268582912UL
|
||||
#define METAL_SIFIVE_SPI0_1_BASE_ADDRESS 268582912UL
|
||||
#define METAL_SIFIVE_SPI0_10024000_SIZE 4096UL
|
||||
#define METAL_SIFIVE_SPI0_1_SIZE 4096UL
|
||||
|
||||
/* From spi@10034000 */
|
||||
#define METAL_SIFIVE_SPI0_10034000_BASE_ADDRESS 268648448UL
|
||||
#define METAL_SIFIVE_SPI0_2_BASE_ADDRESS 268648448UL
|
||||
#define METAL_SIFIVE_SPI0_10034000_SIZE 4096UL
|
||||
#define METAL_SIFIVE_SPI0_2_SIZE 4096UL
|
||||
|
||||
#define METAL_SIFIVE_SPI0
|
||||
#define METAL_SIFIVE_SPI0_SCKDIV 0UL
|
||||
#define METAL_SIFIVE_SPI0_SCKMODE 4UL
|
||||
|
@ -225,6 +268,12 @@
|
|||
#define METAL_SIFIVE_UART0_10013000_SIZE 4096UL
|
||||
#define METAL_SIFIVE_UART0_0_SIZE 4096UL
|
||||
|
||||
/* From serial@10023000 */
|
||||
#define METAL_SIFIVE_UART0_10023000_BASE_ADDRESS 268578816UL
|
||||
#define METAL_SIFIVE_UART0_1_BASE_ADDRESS 268578816UL
|
||||
#define METAL_SIFIVE_UART0_10023000_SIZE 4096UL
|
||||
#define METAL_SIFIVE_UART0_1_SIZE 4096UL
|
||||
|
||||
#define METAL_SIFIVE_UART0
|
||||
#define METAL_SIFIVE_UART0_TXDATA 0UL
|
||||
#define METAL_SIFIVE_UART0_RXDATA 4UL
|
||||
|
@ -234,4 +283,20 @@
|
|||
#define METAL_SIFIVE_UART0_IP 20UL
|
||||
#define METAL_SIFIVE_UART0_DIV 24UL
|
||||
|
||||
#endif /* SIFIVE_HIFIVE1_REVB____METAL_PLATFORM_H*/
|
||||
/* From aon@10000000 */
|
||||
#define METAL_SIFIVE_AON0_10000000_BASE_ADDRESS 268435456UL
|
||||
#define METAL_SIFIVE_AON0_0_BASE_ADDRESS 268435456UL
|
||||
#define METAL_SIFIVE_AON0_10000000_SIZE 32768UL
|
||||
#define METAL_SIFIVE_AON0_0_SIZE 32768UL
|
||||
|
||||
#define METAL_SIFIVE_WDOG0
|
||||
#define METAL_SIFIVE_WDOG0_MAGIC_KEY 5370206UL
|
||||
#define METAL_SIFIVE_WDOG0_MAGIC_FOOD 218755085UL
|
||||
#define METAL_SIFIVE_WDOG0_WDOGCFG 0UL
|
||||
#define METAL_SIFIVE_WDOG0_WDOGCOUNT 8UL
|
||||
#define METAL_SIFIVE_WDOG0_WDOGS 16UL
|
||||
#define METAL_SIFIVE_WDOG0_WDOGFEED 24UL
|
||||
#define METAL_SIFIVE_WDOG0_WDOGKEY 28UL
|
||||
#define METAL_SIFIVE_WDOG0_WDOGCMP 32UL
|
||||
|
||||
#endif /* METAL_PLATFORM_H*/
|
||||
|
|
|
@ -1,67 +1,156 @@
|
|||
/* Copyright 2019 SiFive, Inc */
|
||||
/* Copyright (c) 2020 SiFive Inc. */
|
||||
/* SPDX-License-Identifier: Apache-2.0 */
|
||||
/* ----------------------------------- */
|
||||
/* ----------------------------------- */
|
||||
|
||||
OUTPUT_ARCH("riscv")
|
||||
|
||||
/* Default Linker Script
|
||||
*
|
||||
* This is the default linker script for all Freedom Metal applications.
|
||||
*/
|
||||
|
||||
ENTRY(_enter)
|
||||
|
||||
MEMORY
|
||||
{
|
||||
ram (wxa!ri) : ORIGIN = 0x80000000, LENGTH = 0x4000
|
||||
flash (rxai!w) : ORIGIN = 0x20010000, LENGTH = 0x6a120
|
||||
itim (airwx) : ORIGIN = 0x8000000, LENGTH = 0x2000
|
||||
ram (arw!xi) : ORIGIN = 0x80000000, LENGTH = 0x4000
|
||||
rom (irx!wa) : ORIGIN = 0x20010000, LENGTH = 0x6a120
|
||||
}
|
||||
|
||||
PHDRS
|
||||
{
|
||||
flash PT_LOAD;
|
||||
rom PT_LOAD;
|
||||
ram_init PT_LOAD;
|
||||
tls PT_TLS;
|
||||
ram PT_LOAD;
|
||||
itim_init PT_LOAD;
|
||||
ram PT_NULL;
|
||||
itim PT_NULL;
|
||||
text PT_LOAD;
|
||||
lim_init PT_LOAD;
|
||||
}
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
/* Each hart is allocated its own stack of size __stack_size. This value
|
||||
* can be overriden at build-time by adding the following to CFLAGS:
|
||||
*
|
||||
* -Xlinker --defsym=__stack_size=0xf00
|
||||
*
|
||||
* where 0xf00 can be replaced with a multiple of 16 of your choice.
|
||||
*
|
||||
* __stack_size is PROVIDE-ed as a symbol so that initialization code
|
||||
* initializes the stack pointers for each hart at the right offset from
|
||||
* the _sp symbol.
|
||||
*/
|
||||
__stack_size = DEFINED(__stack_size) ? __stack_size : 0x400;
|
||||
PROVIDE(__stack_size = __stack_size);
|
||||
__heap_size = DEFINED(__heap_size) ? __heap_size : 0x4;
|
||||
|
||||
/* The size of the heap can be overriden at build-time by adding the
|
||||
* following to CFLAGS:
|
||||
*
|
||||
* -Xlinker --defsym=__heap_size=0xf00
|
||||
*
|
||||
* where 0xf00 can be replaced with the value of your choice.
|
||||
*
|
||||
* Altertatively, the heap can be grown to fill the entire remaining region
|
||||
* of RAM by adding the following to CFLAGS:
|
||||
*
|
||||
* -Xlinker --defsym=__heap_max=1
|
||||
*
|
||||
* Note that depending on the memory layout, the bitness (32/64bit) of the
|
||||
* target, and the code model in use, this might cause a relocation error.
|
||||
*/
|
||||
__heap_size = DEFINED(__heap_size) ? __heap_size : 0x800;
|
||||
|
||||
/* The boot hart sets which hart runs the pre-main initialization routines,
|
||||
* including copying .data into RAM, zeroing the BSS region, running
|
||||
* constructors, etc. After initialization, the boot hart is also the only
|
||||
* hart which runs application code unless the application overrides the
|
||||
* secondary_main() function to start execution on secondary harts.
|
||||
*/
|
||||
PROVIDE(__metal_boot_hart = 0);
|
||||
PROVIDE(__metal_chicken_bit = 0);
|
||||
|
||||
/* The chicken bit is used by pre-main initialization to enable/disable
|
||||
* certain core features */
|
||||
PROVIDE(__metal_chicken_bit = 1);
|
||||
|
||||
.init :
|
||||
{
|
||||
/* The memory_ecc_scrub bit is used by _entry code to enable/disable
|
||||
* memories scrubbing to zero */
|
||||
PROVIDE(__metal_eccscrub_bit = 0);
|
||||
|
||||
/* The RAM memories map for ECC scrubbing */
|
||||
PROVIDE( metal_dtim_0_memory_start = 0x80000000 );
|
||||
PROVIDE( metal_dtim_0_memory_end = 0x80000000 + 0x4000 );
|
||||
PROVIDE( metal_itim_0_memory_start = 0x8000000 );
|
||||
PROVIDE( metal_itim_0_memory_end = 0x8000000 + 0x2000 );
|
||||
|
||||
/* ROM SECTION
|
||||
*
|
||||
* The following sections contain data which lives in read-only memory, if
|
||||
* such memory is present in the design, for the entire duration of program
|
||||
* execution.
|
||||
*/
|
||||
|
||||
.init : {
|
||||
/* The _enter symbol is placed in the .text.metal.init.enter section
|
||||
* and must be placed at the beginning of the program */
|
||||
KEEP (*(.text.metal.init.enter))
|
||||
KEEP (*(.text.metal.init.*))
|
||||
KEEP (*(SORT_NONE(.init)))
|
||||
KEEP (*(.text.libgloss.start))
|
||||
} >flash AT>flash :flash
|
||||
} >rom :rom
|
||||
|
||||
|
||||
.text :
|
||||
{
|
||||
*(.text.unlikely .text.unlikely.*)
|
||||
*(.text.startup .text.startup.*)
|
||||
*(.text .text.*)
|
||||
*(.itim .itim.*)
|
||||
*(.gnu.linkonce.t.*)
|
||||
} >flash AT>flash :flash
|
||||
|
||||
|
||||
.fini :
|
||||
{
|
||||
.fini : {
|
||||
KEEP (*(SORT_NONE(.fini)))
|
||||
} >flash AT>flash :flash
|
||||
} >rom :rom
|
||||
|
||||
.preinit_array : ALIGN(8) {
|
||||
PROVIDE_HIDDEN (__preinit_array_start = .);
|
||||
KEEP (*(.preinit_array))
|
||||
PROVIDE_HIDDEN (__preinit_array_end = .);
|
||||
} >rom :rom
|
||||
|
||||
.init_array : ALIGN(8) {
|
||||
PROVIDE_HIDDEN (__init_array_start = .);
|
||||
KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*)))
|
||||
KEEP (*(.init_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .ctors))
|
||||
PROVIDE_HIDDEN (__init_array_end = .);
|
||||
PROVIDE_HIDDEN ( metal_constructors_start = .);
|
||||
KEEP (*(SORT_BY_INIT_PRIORITY(.metal.init_array.*)));
|
||||
KEEP (*(.metal.init_array));
|
||||
PROVIDE_HIDDEN ( metal_constructors_end = .);
|
||||
} >rom :rom
|
||||
|
||||
.fini_array : ALIGN(8) {
|
||||
PROVIDE_HIDDEN (__fini_array_start = .);
|
||||
KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*)))
|
||||
KEEP (*(.fini_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .dtors))
|
||||
PROVIDE_HIDDEN (__fini_array_end = .);
|
||||
PROVIDE_HIDDEN ( metal_destructors_start = .);
|
||||
KEEP (*(SORT_BY_INIT_PRIORITY(.metal.fini_array.*)));
|
||||
KEEP (*(.metal.fini_array));
|
||||
PROVIDE_HIDDEN ( metal_destructors_end = .);
|
||||
} >rom :rom
|
||||
|
||||
|
||||
PROVIDE (__etext = .);
|
||||
PROVIDE (_etext = .);
|
||||
PROVIDE (etext = .);
|
||||
|
||||
.ctors : {
|
||||
KEEP (*crtbegin.o(.ctors))
|
||||
KEEP (*crtbegin?.o(.ctors))
|
||||
KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors))
|
||||
KEEP (*(SORT(.ctors.*)))
|
||||
KEEP (*(.ctors))
|
||||
KEEP (*(.metal.ctors .metal.ctors.*))
|
||||
} >rom :rom
|
||||
|
||||
.rodata :
|
||||
{
|
||||
.dtors : {
|
||||
KEEP (*crtbegin.o(.dtors))
|
||||
KEEP (*crtbegin?.o(.dtors))
|
||||
KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors))
|
||||
KEEP (*(SORT(.dtors.*)))
|
||||
KEEP (*(.dtors))
|
||||
KEEP (*(.metal.dtors .metal.dtors.*))
|
||||
} >rom : rom
|
||||
|
||||
.rodata : {
|
||||
*(.rdata)
|
||||
*(.rodata .rodata.*)
|
||||
*(.gnu.linkonce.r.*)
|
||||
|
@ -71,166 +160,143 @@ SECTIONS
|
|||
*(.srodata.cst4)
|
||||
*(.srodata.cst2)
|
||||
*(.srodata .srodata.*)
|
||||
} >flash AT>flash :flash
|
||||
} >rom :rom
|
||||
|
||||
/* ITIM SECTION
|
||||
*
|
||||
* The following sections contain data which is copied from read-only
|
||||
* memory into an instruction tightly-integrated memory (ITIM), if one
|
||||
* is present in the design, during pre-main program initialization.
|
||||
*
|
||||
* Generally, the data copied into the ITIM should be performance-critical
|
||||
* functions which benefit from low instruction-fetch latency.
|
||||
*/
|
||||
|
||||
. = ALIGN(4);
|
||||
|
||||
|
||||
.preinit_array :
|
||||
{
|
||||
PROVIDE_HIDDEN (__preinit_array_start = .);
|
||||
KEEP (*(.preinit_array))
|
||||
PROVIDE_HIDDEN (__preinit_array_end = .);
|
||||
} >flash AT>flash :flash
|
||||
|
||||
|
||||
.init_array :
|
||||
{
|
||||
PROVIDE_HIDDEN (__init_array_start = .);
|
||||
KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*)))
|
||||
KEEP (*(.init_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .ctors))
|
||||
PROVIDE_HIDDEN (__init_array_end = .);
|
||||
} >flash AT>flash :flash
|
||||
|
||||
|
||||
.fini_array :
|
||||
{
|
||||
PROVIDE_HIDDEN (__fini_array_start = .);
|
||||
KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*)))
|
||||
KEEP (*(.fini_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .dtors))
|
||||
PROVIDE_HIDDEN (__fini_array_end = .);
|
||||
} >flash AT>flash :flash
|
||||
|
||||
|
||||
.ctors :
|
||||
{
|
||||
/* gcc uses crtbegin.o to find the start of
|
||||
the constructors, so we make sure it is
|
||||
first. Because this is a wildcard, it
|
||||
doesn't matter if the user does not
|
||||
actually link against crtbegin.o; the
|
||||
linker won't look for a file to match a
|
||||
wildcard. The wildcard also means that it
|
||||
doesn't matter which directory crtbegin.o
|
||||
is in. */
|
||||
KEEP (*crtbegin.o(.ctors))
|
||||
KEEP (*crtbegin?.o(.ctors))
|
||||
/* We don't want to include the .ctor section from
|
||||
the crtend.o file until after the sorted ctors.
|
||||
The .ctor section from the crtend file contains the
|
||||
end of ctors marker and it must be last */
|
||||
KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors))
|
||||
KEEP (*(SORT(.ctors.*)))
|
||||
KEEP (*(.ctors))
|
||||
} >flash AT>flash :flash
|
||||
|
||||
|
||||
.dtors :
|
||||
{
|
||||
KEEP (*crtbegin.o(.dtors))
|
||||
KEEP (*crtbegin?.o(.dtors))
|
||||
KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors))
|
||||
KEEP (*(SORT(.dtors.*)))
|
||||
KEEP (*(.dtors))
|
||||
} >flash AT>flash :flash
|
||||
|
||||
|
||||
.litimalign :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
PROVIDE( metal_segment_itim_source_start = . );
|
||||
} >flash AT>flash :flash
|
||||
|
||||
|
||||
.ditimalign :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
PROVIDE( metal_segment_itim_target_start = . );
|
||||
} >ram AT>flash :ram_init
|
||||
|
||||
|
||||
.itim :
|
||||
{
|
||||
.itim : ALIGN(8) {
|
||||
*(.itim .itim.*)
|
||||
} >flash AT>flash :flash
|
||||
} >itim AT>rom :itim_init
|
||||
|
||||
PROVIDE( metal_segment_itim_source_start = LOADADDR(.itim) );
|
||||
PROVIDE( metal_segment_itim_target_start = ADDR(.itim) );
|
||||
PROVIDE( metal_segment_itim_target_end = ADDR(.itim) + SIZEOF(.itim) );
|
||||
|
||||
. = ALIGN(8);
|
||||
PROVIDE( metal_segment_itim_target_end = . );
|
||||
/* LIM SECTION
|
||||
*
|
||||
* The following sections contain data which is copied from read-only
|
||||
* memory into a loosely integrated memory (LIM), which is shared with L2
|
||||
* cache, during pre-main program initialization.
|
||||
*
|
||||
* Generally, the data copied into the LIM should be performance-critical
|
||||
* functions which benefit from low instruction-fetch latency.
|
||||
*/
|
||||
|
||||
.lim : ALIGN(8) {
|
||||
*(.lim .lim.*)
|
||||
} >ram AT>rom :lim_init
|
||||
|
||||
.lalign :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
PROVIDE( _data_lma = . );
|
||||
PROVIDE( metal_segment_data_source_start = . );
|
||||
} >flash AT>flash :flash
|
||||
PROVIDE( metal_segment_lim_source_start = LOADADDR(.lim) );
|
||||
PROVIDE( metal_segment_lim_target_start = ADDR(.lim) );
|
||||
PROVIDE( metal_segment_lim_target_end = ADDR(.lim) + SIZEOF(.lim) );
|
||||
|
||||
/* TEXT SECTION
|
||||
*
|
||||
* The following section contains the code of the program, excluding
|
||||
* everything that's been allocated into the ITIM/LIM already
|
||||
*/
|
||||
|
||||
.dalign :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
PROVIDE( metal_segment_data_target_start = . );
|
||||
} >ram AT>flash :ram_init
|
||||
.text : {
|
||||
*(.text.unlikely .text.unlikely.*)
|
||||
*(.text.startup .text.startup.*)
|
||||
*(.text .text.*)
|
||||
*(.gnu.linkonce.t.*)
|
||||
} >rom :text
|
||||
|
||||
/* RAM SECTION
|
||||
*
|
||||
* The following sections contain data which is copied from read-only
|
||||
* memory into a read-write-capable memory such as data tightly-integrated
|
||||
* memory (DTIM) or another main memory, as well as the BSS, stack, and
|
||||
* heap.
|
||||
*
|
||||
* You might notice that .data, .tdata, .tbss, .tbss_space, and .bss all
|
||||
* have an apparently unnecessary ALIGN at their top. This is because
|
||||
* the implementation of _start in Freedom Metal libgloss depends on the
|
||||
* ADDR and LOADADDR being 8-byte aligned.
|
||||
*/
|
||||
|
||||
.data :
|
||||
{
|
||||
.data : ALIGN(8) {
|
||||
*(.data .data.*)
|
||||
*(.gnu.linkonce.d.*)
|
||||
. = ALIGN(8);
|
||||
PROVIDE( __global_pointer$ = . + 0x800 );
|
||||
*(.sdata .sdata.* .sdata2.*)
|
||||
*(.gnu.linkonce.s.*)
|
||||
} >ram AT>flash :ram_init
|
||||
} >ram AT>rom :ram_init
|
||||
|
||||
.tdata : ALIGN(8) {
|
||||
PROVIDE( __tls_base = . );
|
||||
*(.tdata .tdata.* .gnu.linkonce.td.*)
|
||||
} >ram AT>rom :tls :ram_init
|
||||
|
||||
. = ALIGN(4);
|
||||
PROVIDE( _edata = . );
|
||||
PROVIDE( edata = . );
|
||||
PROVIDE( metal_segment_data_target_end = . );
|
||||
PROVIDE( _fbss = . );
|
||||
PROVIDE( __bss_start = . );
|
||||
PROVIDE( metal_segment_bss_target_start = . );
|
||||
PROVIDE( __tdata_source = LOADADDR(.tdata) );
|
||||
PROVIDE( __tdata_size = SIZEOF(.tdata) );
|
||||
|
||||
PROVIDE( metal_segment_data_source_start = LOADADDR(.data) );
|
||||
PROVIDE( metal_segment_data_target_start = ADDR(.data) );
|
||||
PROVIDE( metal_segment_data_target_end = ADDR(.tdata) + SIZEOF(.tdata) );
|
||||
|
||||
.bss :
|
||||
{
|
||||
.tbss : ALIGN(8) {
|
||||
*(.tbss .tbss.* .gnu.linkonce.tb.*)
|
||||
*(.tcommon .tcommon.*)
|
||||
PROVIDE( __tls_end = . );
|
||||
} >ram AT>ram :tls :ram
|
||||
PROVIDE( __tbss_size = SIZEOF(.tbss) );
|
||||
PROVIDE( __tls_size = __tls_end - __tls_base );
|
||||
|
||||
.tbss_space : ALIGN(8) {
|
||||
. = . + __tbss_size;
|
||||
} >ram :ram
|
||||
|
||||
.bss (NOLOAD): ALIGN(8) {
|
||||
*(.sbss*)
|
||||
*(.gnu.linkonce.sb.*)
|
||||
*(.bss .bss.*)
|
||||
*(.gnu.linkonce.b.*)
|
||||
*(COMMON)
|
||||
. = ALIGN(4);
|
||||
} >ram AT>ram :ram
|
||||
} >ram :ram
|
||||
|
||||
PROVIDE( metal_segment_bss_source_start = LOADADDR(.tbss) );
|
||||
PROVIDE( metal_segment_bss_target_start = ADDR(.tbss) );
|
||||
PROVIDE( metal_segment_bss_target_end = ADDR(.bss) + SIZEOF(.bss) );
|
||||
|
||||
|
||||
. = ALIGN(8);
|
||||
PROVIDE( _end = . );
|
||||
PROVIDE( end = . );
|
||||
PROVIDE( metal_segment_bss_target_end = . );
|
||||
|
||||
.stack :
|
||||
{
|
||||
. = ALIGN(16);
|
||||
metal_segment_stack_begin = .;
|
||||
. += __stack_size;
|
||||
. = ALIGN(16);
|
||||
_sp = .;
|
||||
PROVIDE(metal_segment_stack_end = .);
|
||||
.stack (NOLOAD) : ALIGN(16) {
|
||||
PROVIDE(metal_segment_stack_begin = .);
|
||||
. += __stack_size; /* Hart 0 */
|
||||
PROVIDE( _sp = . );
|
||||
__freertos_irq_stack_top = .;
|
||||
} >ram AT>ram :ram
|
||||
PROVIDE(metal_segment_stack_end = .);
|
||||
} >ram :ram
|
||||
|
||||
|
||||
.heap :
|
||||
{
|
||||
.heap (NOLOAD) : ALIGN(8) {
|
||||
PROVIDE( __end = . );
|
||||
PROVIDE( __heap_start = . );
|
||||
PROVIDE( metal_segment_heap_target_start = . );
|
||||
. = __heap_size;
|
||||
/* If __heap_max is defined, grow the heap to use the rest of RAM,
|
||||
* otherwise set the heap size to __heap_size */
|
||||
. = DEFINED(__heap_max) ? MIN( LENGTH(ram) - ( . - ORIGIN(ram)) , 0x10000000) : __heap_size;
|
||||
PROVIDE( metal_segment_heap_target_end = . );
|
||||
PROVIDE( _heap_end = . );
|
||||
} >ram AT>ram :ram
|
||||
|
||||
PROVIDE( __heap_end = . );
|
||||
} >ram :ram
|
||||
|
||||
/* C++ exception handling information is
|
||||
* not useful with our current runtime environment,
|
||||
* and it consumes flash space. Discard it until
|
||||
* we have something that can use it
|
||||
*/
|
||||
/DISCARD/ : {
|
||||
*(.eh_frame .eh_frame.*)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,327 @@
|
|||
/* Copyright (c) 2020 SiFive Inc. */
|
||||
/* SPDX-License-Identifier: Apache-2.0 */
|
||||
OUTPUT_ARCH("riscv")
|
||||
|
||||
/* Privileged mode Linker Script
|
||||
*
|
||||
* This linker script is based on metal.default.lds. It introduce specific
|
||||
* section to isolate (acessible only from machine mode) and others that can be
|
||||
* used in every execution mode. This linker script it tailored for FreeRTOS
|
||||
* applications.
|
||||
*/
|
||||
|
||||
ENTRY(_enter)
|
||||
|
||||
MEMORY
|
||||
{
|
||||
itim (airwx) : ORIGIN = 0x8000000, LENGTH = 0x2000
|
||||
ram (arw!xi) : ORIGIN = 0x80000000, LENGTH = 0x4000
|
||||
rom (irx!wa) : ORIGIN = 0x20010000, LENGTH = 0x6a120
|
||||
}
|
||||
|
||||
PHDRS
|
||||
{
|
||||
rom PT_LOAD;
|
||||
ram_init PT_LOAD;
|
||||
tls PT_TLS;
|
||||
ram PT_LOAD;
|
||||
itim_init PT_LOAD;
|
||||
text PT_LOAD;
|
||||
lim_init PT_LOAD;
|
||||
}
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
/* Each hart is allocated its own stack of size __stack_size. This value
|
||||
* can be overriden at build-time by adding the following to CFLAGS:
|
||||
*
|
||||
* -Xlinker --defsym=__stack_size=0xf00
|
||||
*
|
||||
* where 0xf00 can be replaced with a multiple of 16 of your choice.
|
||||
*
|
||||
* __stack_size is PROVIDE-ed as a symbol so that initialization code
|
||||
* initializes the stack pointers for each hart at the right offset from
|
||||
* the _sp symbol.
|
||||
*/
|
||||
__stack_size = DEFINED(__stack_size) ? __stack_size : 0x400;
|
||||
PROVIDE(__stack_size = __stack_size);
|
||||
|
||||
/* The size of the heap can be overriden at build-time by adding the
|
||||
* following to CFLAGS:
|
||||
*
|
||||
* -Xlinker --defsym=__heap_size=0xf00
|
||||
*
|
||||
* where 0xf00 can be replaced with the value of your choice.
|
||||
*
|
||||
* Altertatively, the heap can be grown to fill the entire remaining region
|
||||
* of RAM by adding the following to CFLAGS:
|
||||
*
|
||||
* -Xlinker --defsym=__heap_max=1
|
||||
*
|
||||
* Note that depending on the memory layout, the bitness (32/64bit) of the
|
||||
* target, and the code model in use, this might cause a relocation error.
|
||||
*/
|
||||
__heap_size = DEFINED(__heap_size) ? __heap_size : 0x800;
|
||||
|
||||
/* The boot hart sets which hart runs the pre-main initialization routines,
|
||||
* including copying .data into RAM, zeroing the BSS region, running
|
||||
* constructors, etc. After initialization, the boot hart is also the only
|
||||
* hart which runs application code unless the application overrides the
|
||||
* secondary_main() function to start execution on secondary harts.
|
||||
*/
|
||||
PROVIDE(__metal_boot_hart = 0);
|
||||
|
||||
/* The chicken bit is used by pre-main initialization to enable/disable
|
||||
* certain core features */
|
||||
PROVIDE(__metal_chicken_bit = 1);
|
||||
|
||||
/* The memory_ecc_scrub bit is used by _entry code to enable/disable
|
||||
* memories scrubbing to zero */
|
||||
PROVIDE(__metal_eccscrub_bit = 0);
|
||||
|
||||
/* The RAM memories map for ECC scrubbing */
|
||||
PROVIDE( metal_dtim_0_memory_start = 0x80000000 );
|
||||
PROVIDE( metal_dtim_0_memory_end = 0x80000000 + 0x4000 );
|
||||
PROVIDE( metal_itim_0_memory_start = 0x8000000 );
|
||||
PROVIDE( metal_itim_0_memory_end = 0x8000000 + 0x2000 );
|
||||
|
||||
/* ROM SECTION
|
||||
*
|
||||
* The following sections contain data which lives in read-only memory, if
|
||||
* such memory is present in the design, for the entire duration of program
|
||||
* execution.
|
||||
*/
|
||||
|
||||
.init : {
|
||||
/* The _enter symbol is placed in the .text.metal.init.enter section
|
||||
* and must be placed at the beginning of the program */
|
||||
KEEP (*(.text.metal.init.enter))
|
||||
KEEP (*(.text.metal.init.*))
|
||||
KEEP (*(SORT_NONE(.init)))
|
||||
KEEP (*(.text.libgloss.start))
|
||||
} >rom :rom
|
||||
|
||||
.fini : {
|
||||
KEEP (*(SORT_NONE(.fini)))
|
||||
} >rom :rom
|
||||
|
||||
.preinit_array : ALIGN(8) {
|
||||
PROVIDE_HIDDEN (__preinit_array_start = .);
|
||||
KEEP (*(.preinit_array))
|
||||
PROVIDE_HIDDEN (__preinit_array_end = .);
|
||||
} >rom :rom
|
||||
|
||||
.init_array : ALIGN(8) {
|
||||
PROVIDE_HIDDEN (__init_array_start = .);
|
||||
KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*)))
|
||||
KEEP (*(.init_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .ctors))
|
||||
PROVIDE_HIDDEN (__init_array_end = .);
|
||||
PROVIDE_HIDDEN ( metal_constructors_start = .);
|
||||
KEEP (*(SORT_BY_INIT_PRIORITY(.metal.init_array.*)));
|
||||
KEEP (*(.metal.init_array));
|
||||
PROVIDE_HIDDEN ( metal_constructors_end = .);
|
||||
} >rom :rom
|
||||
|
||||
.fini_array : ALIGN(8) {
|
||||
PROVIDE_HIDDEN (__fini_array_start = .);
|
||||
KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*)))
|
||||
KEEP (*(.fini_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .dtors))
|
||||
PROVIDE_HIDDEN (__fini_array_end = .);
|
||||
PROVIDE_HIDDEN ( metal_destructors_start = .);
|
||||
KEEP (*(SORT_BY_INIT_PRIORITY(.metal.fini_array.*)));
|
||||
KEEP (*(.metal.fini_array));
|
||||
PROVIDE_HIDDEN ( metal_destructors_end = .);
|
||||
} >rom :rom
|
||||
|
||||
.privileged_functions : ALIGN (32) {
|
||||
__privileged_functions_start__ = .;
|
||||
KEEP(*(privileged_functions))
|
||||
. = ALIGN(32);
|
||||
__privileged_functions_end__ = .;
|
||||
} >rom
|
||||
|
||||
|
||||
.ctors : {
|
||||
. = ALIGN(32);
|
||||
__unprivileged_section_start__ = .;
|
||||
KEEP (*crtbegin.o(.ctors))
|
||||
KEEP (*crtbegin?.o(.ctors))
|
||||
KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors))
|
||||
KEEP (*(SORT(.ctors.*)))
|
||||
KEEP (*(.ctors))
|
||||
KEEP (*(.metal.ctors .metal.ctors.*))
|
||||
} >rom :rom
|
||||
|
||||
.dtors : {
|
||||
KEEP (*crtbegin.o(.dtors))
|
||||
KEEP (*crtbegin?.o(.dtors))
|
||||
KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors))
|
||||
KEEP (*(SORT(.dtors.*)))
|
||||
KEEP (*(.dtors))
|
||||
KEEP (*(.metal.dtors .metal.dtors.*))
|
||||
} >rom : rom
|
||||
|
||||
.rodata : {
|
||||
*(.rdata)
|
||||
*(.rodata .rodata.*)
|
||||
*(.gnu.linkonce.r.*)
|
||||
. = ALIGN(8);
|
||||
*(.srodata.cst16)
|
||||
*(.srodata.cst8)
|
||||
*(.srodata.cst4)
|
||||
*(.srodata.cst2)
|
||||
*(.srodata .srodata.*)
|
||||
} >rom :rom
|
||||
|
||||
/* ITIM SECTION
|
||||
*
|
||||
* The following sections contain data which is copied from read-only
|
||||
* memory into an instruction tightly-integrated memory (ITIM), if one
|
||||
* is present in the design, during pre-main program initialization.
|
||||
*
|
||||
* Generally, the data copied into the ITIM should be performance-critical
|
||||
* functions which benefit from low instruction-fetch latency.
|
||||
*/
|
||||
|
||||
.itim : ALIGN(8) {
|
||||
*(.itim .itim.*)
|
||||
} >itim AT>rom :itim_init
|
||||
|
||||
PROVIDE( metal_segment_itim_source_start = LOADADDR(.itim) );
|
||||
PROVIDE( metal_segment_itim_target_start = ADDR(.itim) );
|
||||
PROVIDE( metal_segment_itim_target_end = ADDR(.itim) + SIZEOF(.itim) );
|
||||
|
||||
/* LIM SECTION
|
||||
*
|
||||
* The following sections contain data which is copied from read-only
|
||||
* memory into a loosely integrated memory (LIM), which is shared with L2
|
||||
* cache, during pre-main program initialization.
|
||||
*
|
||||
* Generally, the data copied into the LIM should be performance-critical
|
||||
* functions which benefit from low instruction-fetch latency.
|
||||
*/
|
||||
|
||||
.lim : ALIGN(8) {
|
||||
*(.lim .lim.*)
|
||||
} >ram AT>rom :lim_init
|
||||
|
||||
PROVIDE( metal_segment_lim_source_start = LOADADDR(.lim) );
|
||||
PROVIDE( metal_segment_lim_target_start = ADDR(.lim) );
|
||||
PROVIDE( metal_segment_lim_target_end = ADDR(.lim) + SIZEOF(.lim) );
|
||||
|
||||
/* TEXT SECTION
|
||||
*
|
||||
* The following section contains the code of the program, excluding
|
||||
* everything that's been allocated into the ITIM/LIM already
|
||||
*/
|
||||
|
||||
.text : {
|
||||
*(.text.unlikely .text.unlikely.*)
|
||||
*(.text.startup .text.startup.*)
|
||||
*(.text .text.*)
|
||||
*(.gnu.linkonce.t.*)
|
||||
*(freertos_system_calls)
|
||||
. = ALIGN(32);
|
||||
__unprivileged_section_end__ = .;
|
||||
} >rom :text
|
||||
|
||||
/* RAM SECTION
|
||||
*
|
||||
* The following sections contain data which is copied from read-only
|
||||
* memory into a read-write-capable memory such as data tightly-integrated
|
||||
* memory (DTIM) or another main memory, as well as the BSS, stack, and
|
||||
* heap.
|
||||
*
|
||||
* You might notice that .data, .tdata, .tbss, .tbss_space, and .bss all
|
||||
* have an apparently unnecessary ALIGN at their top. This is because
|
||||
* the implementation of _start in Freedom Metal libgloss depends on the
|
||||
* ADDR and LOADADDR being 8-byte aligned.
|
||||
*/
|
||||
|
||||
.data : ALIGN(8) {
|
||||
. = ALIGN(32);
|
||||
__unprivileged_data_section_start__ = .;
|
||||
*(.data .data.*)
|
||||
*(.gnu.linkonce.d.*)
|
||||
. = ALIGN(8);
|
||||
PROVIDE( __global_pointer$ = . + 0x800 );
|
||||
*(.sdata .sdata.* .sdata2.*)
|
||||
*(.gnu.linkonce.s.*)
|
||||
} >ram AT>rom :ram_init
|
||||
|
||||
.tdata : ALIGN(8) {
|
||||
PROVIDE( __tls_base = . );
|
||||
*(.tdata .tdata.* .gnu.linkonce.td.*)
|
||||
} >ram AT>rom :tls :ram_init
|
||||
|
||||
PROVIDE( __tdata_source = LOADADDR(.tdata) );
|
||||
PROVIDE( __tdata_size = SIZEOF(.tdata) );
|
||||
|
||||
PROVIDE( metal_segment_data_source_start = LOADADDR(.data) );
|
||||
PROVIDE( metal_segment_data_target_start = ADDR(.data) );
|
||||
PROVIDE( metal_segment_data_target_end = ADDR(.tdata) + SIZEOF(.tdata) );
|
||||
|
||||
.tbss : ALIGN(8) {
|
||||
*(.tbss .tbss.* .gnu.linkonce.tb.*)
|
||||
*(.tcommon .tcommon.*)
|
||||
PROVIDE( __tls_end = . );
|
||||
} >ram AT>ram :tls :ram
|
||||
PROVIDE( __tbss_size = SIZEOF(.tbss) );
|
||||
PROVIDE( __tls_size = __tls_end - __tls_base );
|
||||
|
||||
.tbss_space : ALIGN(8) {
|
||||
. = . + __tbss_size;
|
||||
} >ram :ram
|
||||
|
||||
.bss (NOLOAD): ALIGN(8) {
|
||||
*(.sbss*)
|
||||
*(.gnu.linkonce.sb.*)
|
||||
*(.bss .bss.*)
|
||||
*(.gnu.linkonce.b.*)
|
||||
*(COMMON)
|
||||
. = ALIGN(32);
|
||||
__unprivileged_data_section_end__ = .;
|
||||
} >ram :ram
|
||||
|
||||
PROVIDE( metal_segment_bss_source_start = LOADADDR(.tbss) );
|
||||
PROVIDE( metal_segment_bss_target_start = ADDR(.tbss) );
|
||||
PROVIDE( metal_segment_bss_target_end = ADDR(.bss) + SIZEOF(.bss) );
|
||||
|
||||
.privileged_data (NOLOAD) : ALIGN(32) {
|
||||
__privileged_data_start__ = .;
|
||||
*(privileged_data)
|
||||
/* Non kernel data is kept out of the first _Privileged_Data_Region_Size
|
||||
bytes of SRAM. */
|
||||
. = ALIGN(32);
|
||||
__privileged_data_end__ = .;
|
||||
} >ram
|
||||
|
||||
|
||||
.stack (NOLOAD) : ALIGN(16) {
|
||||
PROVIDE(metal_segment_stack_begin = .);
|
||||
. += __stack_size; /* Hart 0 */
|
||||
PROVIDE( _sp = . );
|
||||
PROVIDE(metal_segment_stack_end = .);
|
||||
} >ram :ram
|
||||
|
||||
.heap (NOLOAD) : ALIGN(8) {
|
||||
PROVIDE( __end = . );
|
||||
PROVIDE( __heap_start = . );
|
||||
PROVIDE( metal_segment_heap_target_start = . );
|
||||
/* If __heap_max is defined, grow the heap to use the rest of RAM,
|
||||
* otherwise set the heap size to __heap_size */
|
||||
. = DEFINED(__heap_max) ? MIN( LENGTH(ram) - ( . - ORIGIN(ram)) , 0x10000000) : __heap_size;
|
||||
PROVIDE( metal_segment_heap_target_end = . );
|
||||
PROVIDE( _heap_end = . );
|
||||
PROVIDE( __heap_end = . );
|
||||
} >ram :ram
|
||||
|
||||
/* C++ exception handling information is
|
||||
* not useful with our current runtime environment,
|
||||
* and it consumes flash space. Discard it until
|
||||
* we have something that can use it
|
||||
*/
|
||||
/DISCARD/ : {
|
||||
*(.eh_frame .eh_frame.*)
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load diff
|
@ -0,0 +1,306 @@
|
|||
/* Copyright (c) 2020 SiFive Inc. */
|
||||
/* SPDX-License-Identifier: Apache-2.0 */
|
||||
OUTPUT_ARCH("riscv")
|
||||
|
||||
/* RAM Read-Only Data Linker Script
|
||||
*
|
||||
* This linker script places application code and read-only data into writable
|
||||
* memories in an attempt to improve performance, since writable memories
|
||||
* are generally lower-latency. This linker script may cause your application
|
||||
* to overflow RAM, since it dramatically increases the quantity of data vying
|
||||
* for space there.
|
||||
*/
|
||||
|
||||
ENTRY(_enter)
|
||||
|
||||
MEMORY
|
||||
{
|
||||
itim (airwx) : ORIGIN = 0x8000000, LENGTH = 0x2000
|
||||
ram (arw!xi) : ORIGIN = 0x80000000, LENGTH = 0x4000
|
||||
rom (irx!wa) : ORIGIN = 0x20010000, LENGTH = 0x6a120
|
||||
}
|
||||
|
||||
PHDRS
|
||||
{
|
||||
rom PT_LOAD;
|
||||
ram_init PT_LOAD;
|
||||
tls PT_TLS;
|
||||
ram PT_LOAD;
|
||||
itim_init PT_LOAD;
|
||||
text PT_LOAD;
|
||||
lim_init PT_LOAD;
|
||||
}
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
/* Each hart is allocated its own stack of size __stack_size. This value
|
||||
* can be overriden at build-time by adding the following to CFLAGS:
|
||||
*
|
||||
* -Xlinker --defsym=__stack_size=0xf00
|
||||
*
|
||||
* where 0xf00 can be replaced with a multiple of 16 of your choice.
|
||||
*
|
||||
* __stack_size is PROVIDE-ed as a symbol so that initialization code
|
||||
* initializes the stack pointers for each hart at the right offset from
|
||||
* the _sp symbol.
|
||||
*/
|
||||
__stack_size = DEFINED(__stack_size) ? __stack_size : 0x400;
|
||||
PROVIDE(__stack_size = __stack_size);
|
||||
|
||||
/* The size of the heap can be overriden at build-time by adding the
|
||||
* following to CFLAGS:
|
||||
*
|
||||
* -Xlinker --defsym=__heap_size=0xf00
|
||||
*
|
||||
* where 0xf00 can be replaced with the value of your choice.
|
||||
*
|
||||
* Altertatively, the heap can be grown to fill the entire remaining region
|
||||
* of RAM by adding the following to CFLAGS:
|
||||
*
|
||||
* -Xlinker --defsym=__heap_max=1
|
||||
*
|
||||
* Note that depending on the memory layout, the bitness (32/64bit) of the
|
||||
* target, and the code model in use, this might cause a relocation error.
|
||||
*/
|
||||
__heap_size = DEFINED(__heap_size) ? __heap_size : 0x800;
|
||||
|
||||
/* The boot hart sets which hart runs the pre-main initialization routines,
|
||||
* including copying .data into RAM, zeroing the BSS region, running
|
||||
* constructors, etc. After initialization, the boot hart is also the only
|
||||
* hart which runs application code unless the application overrides the
|
||||
* secondary_main() function to start execution on secondary harts.
|
||||
*/
|
||||
PROVIDE(__metal_boot_hart = 0);
|
||||
|
||||
/* The chicken bit is used by pre-main initialization to enable/disable
|
||||
* certain core features */
|
||||
PROVIDE(__metal_chicken_bit = 1);
|
||||
|
||||
/* The memory_ecc_scrub bit is used by _entry code to enable/disable
|
||||
* memories scrubbing to zero */
|
||||
PROVIDE(__metal_eccscrub_bit = 0);
|
||||
|
||||
/* The RAM memories map for ECC scrubbing */
|
||||
PROVIDE( metal_dtim_0_memory_start = 0x80000000 );
|
||||
PROVIDE( metal_dtim_0_memory_end = 0x80000000 + 0x4000 );
|
||||
PROVIDE( metal_itim_0_memory_start = 0x8000000 );
|
||||
PROVIDE( metal_itim_0_memory_end = 0x8000000 + 0x2000 );
|
||||
|
||||
/* ROM SECTION
|
||||
*
|
||||
* The following sections contain data which lives in read-only memory, if
|
||||
* such memory is present in the design, for the entire duration of program
|
||||
* execution.
|
||||
*/
|
||||
|
||||
.init : {
|
||||
/* The _enter symbol is placed in the .text.metal.init.enter section
|
||||
* and must be placed at the beginning of the program */
|
||||
KEEP (*(.text.metal.init.enter))
|
||||
KEEP (*(.text.metal.init.*))
|
||||
KEEP (*(SORT_NONE(.init)))
|
||||
KEEP (*(.text.libgloss.start))
|
||||
} >rom :rom
|
||||
|
||||
.fini : {
|
||||
KEEP (*(SORT_NONE(.fini)))
|
||||
} >rom :rom
|
||||
|
||||
.preinit_array : ALIGN(8) {
|
||||
PROVIDE_HIDDEN (__preinit_array_start = .);
|
||||
KEEP (*(.preinit_array))
|
||||
PROVIDE_HIDDEN (__preinit_array_end = .);
|
||||
} >rom :rom
|
||||
|
||||
.init_array : ALIGN(8) {
|
||||
PROVIDE_HIDDEN (__init_array_start = .);
|
||||
KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*)))
|
||||
KEEP (*(.init_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .ctors))
|
||||
PROVIDE_HIDDEN (__init_array_end = .);
|
||||
PROVIDE_HIDDEN ( metal_constructors_start = .);
|
||||
KEEP (*(SORT_BY_INIT_PRIORITY(.metal.init_array.*)));
|
||||
KEEP (*(.metal.init_array));
|
||||
PROVIDE_HIDDEN ( metal_constructors_end = .);
|
||||
} >rom :rom
|
||||
|
||||
.fini_array : ALIGN(8) {
|
||||
PROVIDE_HIDDEN (__fini_array_start = .);
|
||||
KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*)))
|
||||
KEEP (*(.fini_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .dtors))
|
||||
PROVIDE_HIDDEN (__fini_array_end = .);
|
||||
PROVIDE_HIDDEN ( metal_destructors_start = .);
|
||||
KEEP (*(SORT_BY_INIT_PRIORITY(.metal.fini_array.*)));
|
||||
KEEP (*(.metal.fini_array));
|
||||
PROVIDE_HIDDEN ( metal_destructors_end = .);
|
||||
} >rom :rom
|
||||
|
||||
|
||||
|
||||
.ctors : {
|
||||
KEEP (*crtbegin.o(.ctors))
|
||||
KEEP (*crtbegin?.o(.ctors))
|
||||
KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors))
|
||||
KEEP (*(SORT(.ctors.*)))
|
||||
KEEP (*(.ctors))
|
||||
KEEP (*(.metal.ctors .metal.ctors.*))
|
||||
} >rom :rom
|
||||
|
||||
.dtors : {
|
||||
KEEP (*crtbegin.o(.dtors))
|
||||
KEEP (*crtbegin?.o(.dtors))
|
||||
KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors))
|
||||
KEEP (*(SORT(.dtors.*)))
|
||||
KEEP (*(.dtors))
|
||||
KEEP (*(.metal.dtors .metal.dtors.*))
|
||||
} >rom : rom
|
||||
|
||||
|
||||
/* ITIM SECTION
|
||||
*
|
||||
* The following sections contain data which is copied from read-only
|
||||
* memory into an instruction tightly-integrated memory (ITIM), if one
|
||||
* is present in the design, during pre-main program initialization.
|
||||
*
|
||||
* Generally, the data copied into the ITIM should be performance-critical
|
||||
* functions which benefit from low instruction-fetch latency.
|
||||
*/
|
||||
|
||||
.itim : ALIGN(8) {
|
||||
*(.itim .itim.*)
|
||||
} >itim AT>rom :itim_init
|
||||
|
||||
PROVIDE( metal_segment_itim_source_start = LOADADDR(.itim) );
|
||||
PROVIDE( metal_segment_itim_target_start = ADDR(.itim) );
|
||||
PROVIDE( metal_segment_itim_target_end = ADDR(.itim) + SIZEOF(.itim) );
|
||||
|
||||
/* LIM SECTION
|
||||
*
|
||||
* The following sections contain data which is copied from read-only
|
||||
* memory into a loosely integrated memory (LIM), which is shared with L2
|
||||
* cache, during pre-main program initialization.
|
||||
*
|
||||
* Generally, the data copied into the LIM should be performance-critical
|
||||
* functions which benefit from low instruction-fetch latency.
|
||||
*/
|
||||
|
||||
.lim : ALIGN(8) {
|
||||
*(.lim .lim.*)
|
||||
} >ram AT>rom :lim_init
|
||||
|
||||
PROVIDE( metal_segment_lim_source_start = LOADADDR(.lim) );
|
||||
PROVIDE( metal_segment_lim_target_start = ADDR(.lim) );
|
||||
PROVIDE( metal_segment_lim_target_end = ADDR(.lim) + SIZEOF(.lim) );
|
||||
|
||||
/* TEXT SECTION
|
||||
*
|
||||
* The following section contains the code of the program, excluding
|
||||
* everything that's been allocated into the ITIM/LIM already
|
||||
*/
|
||||
|
||||
.text : {
|
||||
*(.text.unlikely .text.unlikely.*)
|
||||
*(.text.startup .text.startup.*)
|
||||
*(.text .text.*)
|
||||
*(.gnu.linkonce.t.*)
|
||||
} >rom :text
|
||||
|
||||
/* RAM SECTION
|
||||
*
|
||||
* The following sections contain data which is copied from read-only
|
||||
* memory into a read-write-capable memory such as data tightly-integrated
|
||||
* memory (DTIM) or another main memory, as well as the BSS, stack, and
|
||||
* heap.
|
||||
*
|
||||
* You might notice that .data, .tdata, .tbss, .tbss_space, and .bss all
|
||||
* have an apparently unnecessary ALIGN at their top. This is because
|
||||
* the implementation of _start in Freedom Metal libgloss depends on the
|
||||
* ADDR and LOADADDR being 8-byte aligned.
|
||||
*/
|
||||
|
||||
.data : ALIGN(8) {
|
||||
*(.data .data.*)
|
||||
*(.gnu.linkonce.d.*)
|
||||
. = ALIGN(8);
|
||||
PROVIDE( __global_pointer$ = . + 0x800 );
|
||||
*(.sdata .sdata.* .sdata2.*)
|
||||
*(.gnu.linkonce.s.*)
|
||||
/* Read-only data is placed in RAM to improve performance, since
|
||||
* read-only memory generally has higher latency than RAM */
|
||||
. = ALIGN(8);
|
||||
*(.srodata.cst16)
|
||||
*(.srodata.cst8)
|
||||
*(.srodata.cst4)
|
||||
*(.srodata.cst2)
|
||||
*(.srodata .srodata.*)
|
||||
. = ALIGN(8);
|
||||
*(.rdata)
|
||||
*(.rodata .rodata.*)
|
||||
*(.gnu.linkonce.r.*)
|
||||
} >ram AT>rom :ram_init
|
||||
|
||||
.tdata : ALIGN(8) {
|
||||
PROVIDE( __tls_base = . );
|
||||
*(.tdata .tdata.* .gnu.linkonce.td.*)
|
||||
} >ram AT>rom :tls :ram_init
|
||||
|
||||
PROVIDE( __tdata_source = LOADADDR(.tdata) );
|
||||
PROVIDE( __tdata_size = SIZEOF(.tdata) );
|
||||
|
||||
PROVIDE( metal_segment_data_source_start = LOADADDR(.data) );
|
||||
PROVIDE( metal_segment_data_target_start = ADDR(.data) );
|
||||
PROVIDE( metal_segment_data_target_end = ADDR(.tdata) + SIZEOF(.tdata) );
|
||||
|
||||
.tbss : ALIGN(8) {
|
||||
*(.tbss .tbss.* .gnu.linkonce.tb.*)
|
||||
*(.tcommon .tcommon.*)
|
||||
PROVIDE( __tls_end = . );
|
||||
} >ram AT>ram :tls :ram
|
||||
PROVIDE( __tbss_size = SIZEOF(.tbss) );
|
||||
PROVIDE( __tls_size = __tls_end - __tls_base );
|
||||
|
||||
.tbss_space : ALIGN(8) {
|
||||
. = . + __tbss_size;
|
||||
} >ram :ram
|
||||
|
||||
.bss (NOLOAD): ALIGN(8) {
|
||||
*(.sbss*)
|
||||
*(.gnu.linkonce.sb.*)
|
||||
*(.bss .bss.*)
|
||||
*(.gnu.linkonce.b.*)
|
||||
*(COMMON)
|
||||
} >ram :ram
|
||||
|
||||
PROVIDE( metal_segment_bss_source_start = LOADADDR(.tbss) );
|
||||
PROVIDE( metal_segment_bss_target_start = ADDR(.tbss) );
|
||||
PROVIDE( metal_segment_bss_target_end = ADDR(.bss) + SIZEOF(.bss) );
|
||||
|
||||
|
||||
|
||||
.stack (NOLOAD) : ALIGN(16) {
|
||||
PROVIDE(metal_segment_stack_begin = .);
|
||||
. += __stack_size; /* Hart 0 */
|
||||
PROVIDE( _sp = . );
|
||||
PROVIDE(metal_segment_stack_end = .);
|
||||
} >ram :ram
|
||||
|
||||
.heap (NOLOAD) : ALIGN(8) {
|
||||
PROVIDE( __end = . );
|
||||
PROVIDE( __heap_start = . );
|
||||
PROVIDE( metal_segment_heap_target_start = . );
|
||||
/* If __heap_max is defined, grow the heap to use the rest of RAM,
|
||||
* otherwise set the heap size to __heap_size */
|
||||
. = DEFINED(__heap_max) ? MIN( LENGTH(ram) - ( . - ORIGIN(ram)) , 0x10000000) : __heap_size;
|
||||
PROVIDE( metal_segment_heap_target_end = . );
|
||||
PROVIDE( _heap_end = . );
|
||||
PROVIDE( __heap_end = . );
|
||||
} >ram :ram
|
||||
|
||||
/* C++ exception handling information is
|
||||
* not useful with our current runtime environment,
|
||||
* and it consumes flash space. Discard it until
|
||||
* we have something that can use it
|
||||
*/
|
||||
/DISCARD/ : {
|
||||
*(.eh_frame .eh_frame.*)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,294 @@
|
|||
/* Copyright (c) 2020 SiFive Inc. */
|
||||
/* SPDX-License-Identifier: Apache-2.0 */
|
||||
OUTPUT_ARCH("riscv")
|
||||
|
||||
/* Scratchpad Linker Script
|
||||
*
|
||||
* This linker script is for executing in "scratchpad" mode, where all
|
||||
* application code and data is placed in writable memory.
|
||||
*/
|
||||
|
||||
ENTRY(_enter)
|
||||
|
||||
MEMORY
|
||||
{
|
||||
itim (airwx) : ORIGIN = 0x8000000, LENGTH = 0x2000
|
||||
ram (arw!xi) : ORIGIN = 0x80000000, LENGTH = 0x4000
|
||||
rom (irx!wa) : ORIGIN = 0x20010000, LENGTH = 0x6a120
|
||||
}
|
||||
|
||||
PHDRS
|
||||
{
|
||||
rom PT_LOAD;
|
||||
ram_init PT_LOAD;
|
||||
tls PT_TLS;
|
||||
ram PT_LOAD;
|
||||
itim_init PT_LOAD;
|
||||
text PT_LOAD;
|
||||
lim_init PT_LOAD;
|
||||
}
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
/* Each hart is allocated its own stack of size __stack_size. This value
|
||||
* can be overriden at build-time by adding the following to CFLAGS:
|
||||
*
|
||||
* -Xlinker --defsym=__stack_size=0xf00
|
||||
*
|
||||
* where 0xf00 can be replaced with a multiple of 16 of your choice.
|
||||
*
|
||||
* __stack_size is PROVIDE-ed as a symbol so that initialization code
|
||||
* initializes the stack pointers for each hart at the right offset from
|
||||
* the _sp symbol.
|
||||
*/
|
||||
__stack_size = DEFINED(__stack_size) ? __stack_size : 0x400;
|
||||
PROVIDE(__stack_size = __stack_size);
|
||||
|
||||
/* The size of the heap can be overriden at build-time by adding the
|
||||
* following to CFLAGS:
|
||||
*
|
||||
* -Xlinker --defsym=__heap_size=0xf00
|
||||
*
|
||||
* where 0xf00 can be replaced with the value of your choice.
|
||||
*
|
||||
* Altertatively, the heap can be grown to fill the entire remaining region
|
||||
* of RAM by adding the following to CFLAGS:
|
||||
*
|
||||
* -Xlinker --defsym=__heap_max=1
|
||||
*
|
||||
* Note that depending on the memory layout, the bitness (32/64bit) of the
|
||||
* target, and the code model in use, this might cause a relocation error.
|
||||
*/
|
||||
__heap_size = DEFINED(__heap_size) ? __heap_size : 0x800;
|
||||
|
||||
/* The boot hart sets which hart runs the pre-main initialization routines,
|
||||
* including copying .data into RAM, zeroing the BSS region, running
|
||||
* constructors, etc. After initialization, the boot hart is also the only
|
||||
* hart which runs application code unless the application overrides the
|
||||
* secondary_main() function to start execution on secondary harts.
|
||||
*/
|
||||
PROVIDE(__metal_boot_hart = 0);
|
||||
|
||||
/* The chicken bit is used by pre-main initialization to enable/disable
|
||||
* certain core features */
|
||||
PROVIDE(__metal_chicken_bit = 1);
|
||||
|
||||
PROVIDE(__metal_eccscrub_bit = 0);
|
||||
|
||||
/* ROM SECTION
|
||||
*
|
||||
* The following sections contain data which lives in read-only memory, if
|
||||
* such memory is present in the design, for the entire duration of program
|
||||
* execution.
|
||||
*/
|
||||
|
||||
.init : {
|
||||
/* The _enter symbol is placed in the .text.metal.init.enter section
|
||||
* and must be placed at the beginning of the program */
|
||||
KEEP (*(.text.metal.init.enter))
|
||||
KEEP (*(.text.metal.init.*))
|
||||
KEEP (*(SORT_NONE(.init)))
|
||||
KEEP (*(.text.libgloss.start))
|
||||
} >ram :rom
|
||||
|
||||
.fini : {
|
||||
KEEP (*(SORT_NONE(.fini)))
|
||||
} >ram :rom
|
||||
|
||||
.preinit_array : ALIGN(8) {
|
||||
PROVIDE_HIDDEN (__preinit_array_start = .);
|
||||
KEEP (*(.preinit_array))
|
||||
PROVIDE_HIDDEN (__preinit_array_end = .);
|
||||
} >ram :rom
|
||||
|
||||
.init_array : ALIGN(8) {
|
||||
PROVIDE_HIDDEN (__init_array_start = .);
|
||||
KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*)))
|
||||
KEEP (*(.init_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .ctors))
|
||||
PROVIDE_HIDDEN (__init_array_end = .);
|
||||
PROVIDE_HIDDEN ( metal_constructors_start = .);
|
||||
KEEP (*(SORT_BY_INIT_PRIORITY(.metal.init_array.*)));
|
||||
KEEP (*(.metal.init_array));
|
||||
PROVIDE_HIDDEN ( metal_constructors_end = .);
|
||||
} >ram :rom
|
||||
|
||||
.fini_array : ALIGN(8) {
|
||||
PROVIDE_HIDDEN (__fini_array_start = .);
|
||||
KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*)))
|
||||
KEEP (*(.fini_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .dtors))
|
||||
PROVIDE_HIDDEN (__fini_array_end = .);
|
||||
PROVIDE_HIDDEN ( metal_destructors_start = .);
|
||||
KEEP (*(SORT_BY_INIT_PRIORITY(.metal.fini_array.*)));
|
||||
KEEP (*(.metal.fini_array));
|
||||
PROVIDE_HIDDEN ( metal_destructors_end = .);
|
||||
} >ram :rom
|
||||
|
||||
|
||||
|
||||
.ctors : {
|
||||
KEEP (*crtbegin.o(.ctors))
|
||||
KEEP (*crtbegin?.o(.ctors))
|
||||
KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors))
|
||||
KEEP (*(SORT(.ctors.*)))
|
||||
KEEP (*(.ctors))
|
||||
KEEP (*(.metal.ctors .metal.ctors.*))
|
||||
} >ram :rom
|
||||
|
||||
.dtors : {
|
||||
KEEP (*crtbegin.o(.dtors))
|
||||
KEEP (*crtbegin?.o(.dtors))
|
||||
KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors))
|
||||
KEEP (*(SORT(.dtors.*)))
|
||||
KEEP (*(.dtors))
|
||||
KEEP (*(.metal.dtors .metal.dtors.*))
|
||||
} >ram : rom
|
||||
|
||||
.rodata : {
|
||||
*(.rdata)
|
||||
*(.rodata .rodata.*)
|
||||
*(.gnu.linkonce.r.*)
|
||||
. = ALIGN(8);
|
||||
*(.srodata.cst16)
|
||||
*(.srodata.cst8)
|
||||
*(.srodata.cst4)
|
||||
*(.srodata.cst2)
|
||||
*(.srodata .srodata.*)
|
||||
} >ram :rom
|
||||
|
||||
/* ITIM SECTION
|
||||
*
|
||||
* The following sections contain data which is copied from read-only
|
||||
* memory into an instruction tightly-integrated memory (ITIM), if one
|
||||
* is present in the design, during pre-main program initialization.
|
||||
*
|
||||
* Generally, the data copied into the ITIM should be performance-critical
|
||||
* functions which benefit from low instruction-fetch latency.
|
||||
*/
|
||||
|
||||
.itim : ALIGN(8) {
|
||||
*(.itim .itim.*)
|
||||
} >itim AT>ram :itim_init
|
||||
|
||||
PROVIDE( metal_segment_itim_source_start = LOADADDR(.itim) );
|
||||
PROVIDE( metal_segment_itim_target_start = ADDR(.itim) );
|
||||
PROVIDE( metal_segment_itim_target_end = ADDR(.itim) + SIZEOF(.itim) );
|
||||
|
||||
/* LIM SECTION
|
||||
*
|
||||
* The following sections contain data which is copied from read-only
|
||||
* memory into a loosely integrated memory (LIM), which is shared with L2
|
||||
* cache, during pre-main program initialization.
|
||||
*
|
||||
* Generally, the data copied into the LIM should be performance-critical
|
||||
* functions which benefit from low instruction-fetch latency.
|
||||
*/
|
||||
|
||||
.lim : ALIGN(8) {
|
||||
*(.lim .lim.*)
|
||||
} >ram AT>ram :lim_init
|
||||
|
||||
PROVIDE( metal_segment_lim_source_start = LOADADDR(.lim) );
|
||||
PROVIDE( metal_segment_lim_target_start = ADDR(.lim) );
|
||||
PROVIDE( metal_segment_lim_target_end = ADDR(.lim) + SIZEOF(.lim) );
|
||||
|
||||
/* TEXT SECTION
|
||||
*
|
||||
* The following section contains the code of the program, excluding
|
||||
* everything that's been allocated into the ITIM/LIM already
|
||||
*/
|
||||
|
||||
.text : {
|
||||
*(.text.unlikely .text.unlikely.*)
|
||||
*(.text.startup .text.startup.*)
|
||||
*(.text .text.*)
|
||||
*(.gnu.linkonce.t.*)
|
||||
} >ram :text
|
||||
|
||||
/* RAM SECTION
|
||||
*
|
||||
* The following sections contain data which is copied from read-only
|
||||
* memory into a read-write-capable memory such as data tightly-integrated
|
||||
* memory (DTIM) or another main memory, as well as the BSS, stack, and
|
||||
* heap.
|
||||
*
|
||||
* You might notice that .data, .tdata, .tbss, .tbss_space, and .bss all
|
||||
* have an apparently unnecessary ALIGN at their top. This is because
|
||||
* the implementation of _start in Freedom Metal libgloss depends on the
|
||||
* ADDR and LOADADDR being 8-byte aligned.
|
||||
*/
|
||||
|
||||
.data : ALIGN(8) {
|
||||
*(.data .data.*)
|
||||
*(.gnu.linkonce.d.*)
|
||||
. = ALIGN(8);
|
||||
PROVIDE( __global_pointer$ = . + 0x800 );
|
||||
*(.sdata .sdata.* .sdata2.*)
|
||||
*(.gnu.linkonce.s.*)
|
||||
} >ram AT>ram :ram_init
|
||||
|
||||
.tdata : ALIGN(8) {
|
||||
PROVIDE( __tls_base = . );
|
||||
*(.tdata .tdata.* .gnu.linkonce.td.*)
|
||||
} >ram AT>ram :tls :ram_init
|
||||
|
||||
PROVIDE( __tdata_source = LOADADDR(.tdata) );
|
||||
PROVIDE( __tdata_size = SIZEOF(.tdata) );
|
||||
|
||||
PROVIDE( metal_segment_data_source_start = LOADADDR(.data) );
|
||||
PROVIDE( metal_segment_data_target_start = ADDR(.data) );
|
||||
PROVIDE( metal_segment_data_target_end = ADDR(.tdata) + SIZEOF(.tdata) );
|
||||
|
||||
.tbss : ALIGN(8) {
|
||||
*(.tbss .tbss.* .gnu.linkonce.tb.*)
|
||||
*(.tcommon .tcommon.*)
|
||||
PROVIDE( __tls_end = . );
|
||||
} >ram AT>ram :tls :ram
|
||||
PROVIDE( __tbss_size = SIZEOF(.tbss) );
|
||||
PROVIDE( __tls_size = __tls_end - __tls_base );
|
||||
|
||||
.tbss_space : ALIGN(8) {
|
||||
. = . + __tbss_size;
|
||||
} >ram :ram
|
||||
|
||||
.bss (NOLOAD): ALIGN(8) {
|
||||
*(.sbss*)
|
||||
*(.gnu.linkonce.sb.*)
|
||||
*(.bss .bss.*)
|
||||
*(.gnu.linkonce.b.*)
|
||||
*(COMMON)
|
||||
} >ram :ram
|
||||
|
||||
PROVIDE( metal_segment_bss_source_start = LOADADDR(.tbss) );
|
||||
PROVIDE( metal_segment_bss_target_start = ADDR(.tbss) );
|
||||
PROVIDE( metal_segment_bss_target_end = ADDR(.bss) + SIZEOF(.bss) );
|
||||
|
||||
|
||||
|
||||
.stack (NOLOAD) : ALIGN(16) {
|
||||
PROVIDE(metal_segment_stack_begin = .);
|
||||
. += __stack_size; /* Hart 0 */
|
||||
PROVIDE( _sp = . );
|
||||
PROVIDE(metal_segment_stack_end = .);
|
||||
} >ram :ram
|
||||
|
||||
.heap (NOLOAD) : ALIGN(8) {
|
||||
PROVIDE( __end = . );
|
||||
PROVIDE( __heap_start = . );
|
||||
PROVIDE( metal_segment_heap_target_start = . );
|
||||
/* If __heap_max is defined, grow the heap to use the rest of RAM,
|
||||
* otherwise set the heap size to __heap_size */
|
||||
. = DEFINED(__heap_max) ? MIN( LENGTH(ram) - ( . - ORIGIN(ram)) , 0x10000000) : __heap_size;
|
||||
PROVIDE( metal_segment_heap_target_end = . );
|
||||
PROVIDE( _heap_end = . );
|
||||
PROVIDE( __heap_end = . );
|
||||
} >ram :ram
|
||||
|
||||
/* C++ exception handling information is
|
||||
* not useful with our current runtime environment,
|
||||
* and it consumes flash space. Discard it until
|
||||
* we have something that can use it
|
||||
*/
|
||||
/DISCARD/ : {
|
||||
*(.eh_frame .eh_frame.*)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
# Copyright (C) 2020 SiFive Inc
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
RISCV_ARCH = rv32imac
|
||||
RISCV_ABI = ilp32
|
||||
RISCV_CMODEL = medlow
|
||||
RISCV_SERIES = sifive-3-series
|
||||
|
||||
TARGET_TAGS = board jlink
|
||||
TARGET_DHRY_ITERS = 20000000
|
||||
TARGET_CORE_ITERS = 5000
|
||||
TARGET_FREERTOS_WAIT_MS = 1000
|
||||
TARGET_INTR_WAIT_CYCLE = 0
|
|
@ -0,0 +1,5 @@
|
|||
BasedOnStyle: LLVM
|
||||
Language: Cpp
|
||||
|
||||
IndentWidth: 4
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
sudo: required
|
||||
|
||||
# Travis doesn't provide a wide variety of host environments to run on, so we
|
||||
# rely on Docker to provide these instead.
|
||||
services:
|
||||
- docker
|
||||
|
||||
# It is not really needed, other than for showing correct language tag in
|
||||
# Travis CI build log.
|
||||
language: c
|
||||
|
||||
# The matrix of targets that we're interested in.
|
||||
env:
|
||||
- HOST="ubuntu:16.04"
|
||||
|
||||
# Before running the install phase we need to set up docker container that runs
|
||||
# the target machine.
|
||||
before_install:
|
||||
- docker run -d --name host -v $(pwd):/travis $HOST tail -f /dev/null
|
||||
- docker ps
|
||||
|
||||
# Update the container and install dependencies
|
||||
install:
|
||||
- docker exec -t host bash -c "yes | apt-get update"
|
||||
- docker exec -t host bash -c "yes | apt-get upgrade"
|
||||
- docker exec -t host bash -c "yes | apt-get install git clang-format-6.0"
|
||||
- sudo curl -L -o /tmp/wake.deb https://github.com/sifive/wake/releases/download/v0.19.0/ubuntu-16-04-wake_0.19.0-1_amd64.deb
|
||||
- sudo apt install /tmp/wake.deb
|
||||
|
||||
# Here's where we actually run the test.
|
||||
script:
|
||||
# Check source code formatting
|
||||
- docker exec -t host bash -c "cd /travis && ./scripts/check-format"
|
||||
# Run dummy Wake program in order to run Wake type checker.
|
||||
- wake --init . && wake -x Unit
|
File diff suppressed because it is too large
Load diff
|
@ -0,0 +1,3 @@
|
|||
This source repository is release under Apache2 and MIT licenses.
|
||||
|
||||
See LICENSE.Apache2 and LICENSE.MIT for details.
|
|
@ -0,0 +1,202 @@
|
|||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
|
@ -0,0 +1,21 @@
|
|||
The MIT License
|
||||
|
||||
Copyright (c) 2019 SiFive, Inc.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
to deal in the Software without restriction, including without limitation
|
||||
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
and/or sell copies of the Software, and to permit persons to whom the
|
||||
Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
|
@ -0,0 +1,238 @@
|
|||
# Copyright 2018-2019 SiFive, Inc
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
########################################################
|
||||
# Sources passed in by configure
|
||||
########################################################
|
||||
|
||||
metal/machine.h: @MACHINE_HEADER@
|
||||
@mkdir -p $(dir $@)
|
||||
cp $< $@
|
||||
|
||||
metal/machine/inline.h: @MACHINE_INLINE@
|
||||
@mkdir -p $(dir $@)
|
||||
cp $< $@
|
||||
|
||||
metal/machine/platform.h: @PLATFORM_HEADER@
|
||||
@mkdir -p $(dir $@)
|
||||
cp $< $@
|
||||
|
||||
nobase_include_HEADERS = \
|
||||
metal/machine.h \
|
||||
metal/machine/inline.h \
|
||||
metal/machine/platform.h
|
||||
|
||||
# This will generate these sources before the compilation step
|
||||
BUILT_SOURCES = \
|
||||
metal/machine.h \
|
||||
metal/machine/inline.h \
|
||||
metal/machine/platform.h
|
||||
|
||||
########################################################
|
||||
# Metal header files
|
||||
########################################################
|
||||
|
||||
nobase_include_HEADERS += \
|
||||
metal/drivers/fixed-clock.h \
|
||||
metal/drivers/fixed-factor-clock.h \
|
||||
metal/drivers/riscv_clint0.h \
|
||||
metal/drivers/riscv_cpu.h \
|
||||
metal/drivers/riscv_plic0.h \
|
||||
metal/drivers/sifive_buserror0.h \
|
||||
metal/drivers/sifive_ccache0.h \
|
||||
metal/drivers/sifive_clic0.h \
|
||||
metal/drivers/sifive_fe310-g000_hfrosc.h \
|
||||
metal/drivers/sifive_fe310-g000_hfxosc.h \
|
||||
metal/drivers/sifive_fe310-g000_lfrosc.h \
|
||||
metal/drivers/sifive_fe310-g000_pll.h \
|
||||
metal/drivers/sifive_fe310-g000_prci.h \
|
||||
metal/drivers/sifive_global-external-interrupts0.h \
|
||||
metal/drivers/sifive_gpio-buttons.h \
|
||||
metal/drivers/sifive_gpio-leds.h \
|
||||
metal/drivers/sifive_gpio-switches.h \
|
||||
metal/drivers/sifive_gpio0.h \
|
||||
metal/drivers/sifive_i2c0.h \
|
||||
metal/drivers/sifive_l2pf0.h \
|
||||
metal/drivers/sifive_local-external-interrupts0.h \
|
||||
metal/drivers/sifive_pwm0.h \
|
||||
metal/drivers/sifive_rtc0.h \
|
||||
metal/drivers/sifive_spi0.h \
|
||||
metal/drivers/sifive_test0.h \
|
||||
metal/drivers/sifive_trace.h \
|
||||
metal/drivers/sifive_uart0.h \
|
||||
metal/drivers/sifive_simuart0.h \
|
||||
metal/drivers/sifive_wdog0.h \
|
||||
metal/drivers/ucb_htif0.h \
|
||||
metal/atomic.h \
|
||||
metal/button.h \
|
||||
metal/cache.h \
|
||||
metal/clock.h \
|
||||
metal/compiler.h \
|
||||
metal/cpu.h \
|
||||
metal/csr.h \
|
||||
metal/gpio.h \
|
||||
metal/hpm.h \
|
||||
metal/i2c.h \
|
||||
metal/init.h \
|
||||
metal/interrupt.h \
|
||||
metal/io.h \
|
||||
metal/itim.h \
|
||||
metal/led.h \
|
||||
metal/lim.h \
|
||||
metal/lock.h \
|
||||
metal/memory.h \
|
||||
metal/pmp.h \
|
||||
metal/privilege.h \
|
||||
metal/pwm.h\
|
||||
metal/rtc.h \
|
||||
metal/shutdown.h \
|
||||
metal/scrub.h \
|
||||
metal/spi.h \
|
||||
metal/switch.h \
|
||||
metal/timer.h \
|
||||
metal/time.h \
|
||||
metal/tty.h \
|
||||
metal/uart.h \
|
||||
metal/watchdog.h
|
||||
|
||||
########################################################
|
||||
# libmetal
|
||||
########################################################
|
||||
|
||||
lib_LIBRARIES = libmetal.a
|
||||
|
||||
libmetal_a_SOURCES = \
|
||||
src/drivers/fixed-clock.c \
|
||||
src/drivers/fixed-factor-clock.c \
|
||||
src/drivers/inline.c \
|
||||
src/drivers/riscv_clint0.c \
|
||||
src/drivers/riscv_cpu.c \
|
||||
src/drivers/riscv_plic0.c \
|
||||
src/drivers/sifive_buserror0.c \
|
||||
src/drivers/sifive_ccache0.c \
|
||||
src/drivers/sifive_clic0.c \
|
||||
src/drivers/sifive_fe310-g000_hfrosc.c \
|
||||
src/drivers/sifive_fe310-g000_hfxosc.c \
|
||||
src/drivers/sifive_fe310-g000_lfrosc.c \
|
||||
src/drivers/sifive_fe310-g000_pll.c \
|
||||
src/drivers/sifive_fe310-g000_prci.c \
|
||||
src/drivers/sifive_global-external-interrupts0.c \
|
||||
src/drivers/sifive_gpio-buttons.c \
|
||||
src/drivers/sifive_gpio-leds.c \
|
||||
src/drivers/sifive_gpio-switches.c \
|
||||
src/drivers/sifive_gpio0.c \
|
||||
src/drivers/sifive_i2c0.c \
|
||||
src/drivers/sifive_l2pf0.c \
|
||||
src/drivers/sifive_local-external-interrupts0.c \
|
||||
src/drivers/sifive_pwm0.c \
|
||||
src/drivers/sifive_rtc0.c \
|
||||
src/drivers/sifive_spi0.c \
|
||||
src/drivers/sifive_test0.c \
|
||||
src/drivers/sifive_trace.c \
|
||||
src/drivers/sifive_uart0.c \
|
||||
src/drivers/sifive_simuart0.c \
|
||||
src/drivers/sifive_wdog0.c \
|
||||
src/drivers/ucb_htif0.c \
|
||||
src/atomic.c \
|
||||
src/button.c \
|
||||
src/cache.c \
|
||||
src/clock.c \
|
||||
src/cpu.c \
|
||||
src/entry.S \
|
||||
src/scrub.S \
|
||||
src/trap.S \
|
||||
src/gpio.c \
|
||||
src/hpm.c \
|
||||
src/i2c.c \
|
||||
src/init.c \
|
||||
src/interrupt.c \
|
||||
src/led.c \
|
||||
src/lock.c \
|
||||
src/memory.c \
|
||||
src/pmp.c \
|
||||
src/privilege.c \
|
||||
src/pwm.c\
|
||||
src/rtc.c \
|
||||
src/shutdown.c \
|
||||
src/spi.c \
|
||||
src/switch.c \
|
||||
src/synchronize_harts.c \
|
||||
src/timer.c \
|
||||
src/time.c \
|
||||
src/trap.S \
|
||||
src/tty.c \
|
||||
src/uart.c \
|
||||
src/vector.S \
|
||||
src/watchdog.c
|
||||
|
||||
########################################################
|
||||
# libsegger
|
||||
########################################################
|
||||
|
||||
# Provide segger hook with Freedom Metal that is built when
|
||||
# --with-builtin-libmetal-segger is passed to configure
|
||||
if WITH_BUILTIN_LIBMETAL_SEGGER
|
||||
|
||||
lib_LIBRARIES += libmetal-segger.a
|
||||
|
||||
libmetal_segger_a_SOURCES = \
|
||||
gloss/crt0.S \
|
||||
segger/SEGGER_target_metal.c
|
||||
|
||||
endif # WITH_BUILTIN_LIBMETAL_SEGGER
|
||||
|
||||
########################################################
|
||||
# libgloss
|
||||
########################################################
|
||||
|
||||
# Freedom Metal has its own libgloss implementation that is only built when
|
||||
# --with-builtin-libgloss is passed to configure.
|
||||
if WITH_BUILTIN_LIBGLOSS
|
||||
|
||||
lib_LIBRARIES += libmetal-gloss.a
|
||||
|
||||
libmetal_gloss_a_SOURCES = \
|
||||
gloss/crt0.S \
|
||||
gloss/nanosleep.c \
|
||||
gloss/sys_access.c \
|
||||
gloss/sys_chdir.c \
|
||||
gloss/sys_chmod.c \
|
||||
gloss/sys_chown.c \
|
||||
gloss/sys_clock_gettime.c \
|
||||
gloss/sys_close.c \
|
||||
gloss/sys_execve.c \
|
||||
gloss/sys_exit.c \
|
||||
gloss/sys_faccessat.c \
|
||||
gloss/sys_fork.c \
|
||||
gloss/sys_fstat.c \
|
||||
gloss/sys_fstatat.c \
|
||||
gloss/sys_ftime.c \
|
||||
gloss/sys_getcwd.c \
|
||||
gloss/sys_getpid.c \
|
||||
gloss/sys_gettimeofday.c \
|
||||
gloss/sys_isatty.c \
|
||||
gloss/sys_kill.c \
|
||||
gloss/sys_link.c \
|
||||
gloss/sys_lseek.c \
|
||||
gloss/sys_lstat.c \
|
||||
gloss/sys_open.c \
|
||||
gloss/sys_openat.c \
|
||||
gloss/sys_read.c \
|
||||
gloss/sys_sbrk.c \
|
||||
gloss/sys_stat.c \
|
||||
gloss/sys_sysconf.c \
|
||||
gloss/sys_times.c \
|
||||
gloss/sys_unlink.c \
|
||||
gloss/sys_utime.c \
|
||||
gloss/sys_wait.c \
|
||||
gloss/sys_write.c
|
||||
|
||||
endif
|
||||
|
||||
########################################################
|
||||
# Clean
|
||||
########################################################
|
||||
|
||||
clean-local:
|
||||
-rm -rf metal/machine.h metal/machine/inline.h
|
||||
-rm -rf metal/machine/platform.h
|
File diff suppressed because it is too large
Load diff
|
@ -0,0 +1,4 @@
|
|||
# Freedom Metal Machine Compatibility Library
|
||||
|
||||
Documentation for the Freedom Metal library [can be found here](https://sifive.github.io/freedom-metal-docs/).
|
||||
|
1268
FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/aclocal.m4
vendored
Normal file
1268
FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/aclocal.m4
vendored
Normal file
File diff suppressed because it is too large
Load diff
270
FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/ar-lib
Executable file
270
FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/ar-lib
Executable file
|
@ -0,0 +1,270 @@
|
|||
#! /bin/sh
|
||||
# Wrapper for Microsoft lib.exe
|
||||
|
||||
me=ar-lib
|
||||
scriptversion=2012-03-01.08; # UTC
|
||||
|
||||
# Copyright (C) 2010-2014 Free Software Foundation, Inc.
|
||||
# Written by Peter Rosin <peda@lysator.liu.se>.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2, or (at your option)
|
||||
# any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
# As a special exception to the GNU General Public License, if you
|
||||
# distribute this file as part of a program that contains a
|
||||
# configuration script generated by Autoconf, you may include it under
|
||||
# the same distribution terms that you use for the rest of that program.
|
||||
|
||||
# This file is maintained in Automake, please report
|
||||
# bugs to <bug-automake@gnu.org> or send patches to
|
||||
# <automake-patches@gnu.org>.
|
||||
|
||||
|
||||
# func_error message
|
||||
func_error ()
|
||||
{
|
||||
echo "$me: $1" 1>&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
file_conv=
|
||||
|
||||
# func_file_conv build_file
|
||||
# Convert a $build file to $host form and store it in $file
|
||||
# Currently only supports Windows hosts.
|
||||
func_file_conv ()
|
||||
{
|
||||
file=$1
|
||||
case $file in
|
||||
/ | /[!/]*) # absolute file, and not a UNC file
|
||||
if test -z "$file_conv"; then
|
||||
# lazily determine how to convert abs files
|
||||
case `uname -s` in
|
||||
MINGW*)
|
||||
file_conv=mingw
|
||||
;;
|
||||
CYGWIN*)
|
||||
file_conv=cygwin
|
||||
;;
|
||||
*)
|
||||
file_conv=wine
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
case $file_conv in
|
||||
mingw)
|
||||
file=`cmd //C echo "$file " | sed -e 's/"\(.*\) " *$/\1/'`
|
||||
;;
|
||||
cygwin)
|
||||
file=`cygpath -m "$file" || echo "$file"`
|
||||
;;
|
||||
wine)
|
||||
file=`winepath -w "$file" || echo "$file"`
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
# func_at_file at_file operation archive
|
||||
# Iterate over all members in AT_FILE performing OPERATION on ARCHIVE
|
||||
# for each of them.
|
||||
# When interpreting the content of the @FILE, do NOT use func_file_conv,
|
||||
# since the user would need to supply preconverted file names to
|
||||
# binutils ar, at least for MinGW.
|
||||
func_at_file ()
|
||||
{
|
||||
operation=$2
|
||||
archive=$3
|
||||
at_file_contents=`cat "$1"`
|
||||
eval set x "$at_file_contents"
|
||||
shift
|
||||
|
||||
for member
|
||||
do
|
||||
$AR -NOLOGO $operation:"$member" "$archive" || exit $?
|
||||
done
|
||||
}
|
||||
|
||||
case $1 in
|
||||
'')
|
||||
func_error "no command. Try '$0 --help' for more information."
|
||||
;;
|
||||
-h | --h*)
|
||||
cat <<EOF
|
||||
Usage: $me [--help] [--version] PROGRAM ACTION ARCHIVE [MEMBER...]
|
||||
|
||||
Members may be specified in a file named with @FILE.
|
||||
EOF
|
||||
exit $?
|
||||
;;
|
||||
-v | --v*)
|
||||
echo "$me, version $scriptversion"
|
||||
exit $?
|
||||
;;
|
||||
esac
|
||||
|
||||
if test $# -lt 3; then
|
||||
func_error "you must specify a program, an action and an archive"
|
||||
fi
|
||||
|
||||
AR=$1
|
||||
shift
|
||||
while :
|
||||
do
|
||||
if test $# -lt 2; then
|
||||
func_error "you must specify a program, an action and an archive"
|
||||
fi
|
||||
case $1 in
|
||||
-lib | -LIB \
|
||||
| -ltcg | -LTCG \
|
||||
| -machine* | -MACHINE* \
|
||||
| -subsystem* | -SUBSYSTEM* \
|
||||
| -verbose | -VERBOSE \
|
||||
| -wx* | -WX* )
|
||||
AR="$AR $1"
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
action=$1
|
||||
shift
|
||||
break
|
||||
;;
|
||||
esac
|
||||
done
|
||||
orig_archive=$1
|
||||
shift
|
||||
func_file_conv "$orig_archive"
|
||||
archive=$file
|
||||
|
||||
# strip leading dash in $action
|
||||
action=${action#-}
|
||||
|
||||
delete=
|
||||
extract=
|
||||
list=
|
||||
quick=
|
||||
replace=
|
||||
index=
|
||||
create=
|
||||
|
||||
while test -n "$action"
|
||||
do
|
||||
case $action in
|
||||
d*) delete=yes ;;
|
||||
x*) extract=yes ;;
|
||||
t*) list=yes ;;
|
||||
q*) quick=yes ;;
|
||||
r*) replace=yes ;;
|
||||
s*) index=yes ;;
|
||||
S*) ;; # the index is always updated implicitly
|
||||
c*) create=yes ;;
|
||||
u*) ;; # TODO: don't ignore the update modifier
|
||||
v*) ;; # TODO: don't ignore the verbose modifier
|
||||
*)
|
||||
func_error "unknown action specified"
|
||||
;;
|
||||
esac
|
||||
action=${action#?}
|
||||
done
|
||||
|
||||
case $delete$extract$list$quick$replace,$index in
|
||||
yes,* | ,yes)
|
||||
;;
|
||||
yesyes*)
|
||||
func_error "more than one action specified"
|
||||
;;
|
||||
*)
|
||||
func_error "no action specified"
|
||||
;;
|
||||
esac
|
||||
|
||||
if test -n "$delete"; then
|
||||
if test ! -f "$orig_archive"; then
|
||||
func_error "archive not found"
|
||||
fi
|
||||
for member
|
||||
do
|
||||
case $1 in
|
||||
@*)
|
||||
func_at_file "${1#@}" -REMOVE "$archive"
|
||||
;;
|
||||
*)
|
||||
func_file_conv "$1"
|
||||
$AR -NOLOGO -REMOVE:"$file" "$archive" || exit $?
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
elif test -n "$extract"; then
|
||||
if test ! -f "$orig_archive"; then
|
||||
func_error "archive not found"
|
||||
fi
|
||||
if test $# -gt 0; then
|
||||
for member
|
||||
do
|
||||
case $1 in
|
||||
@*)
|
||||
func_at_file "${1#@}" -EXTRACT "$archive"
|
||||
;;
|
||||
*)
|
||||
func_file_conv "$1"
|
||||
$AR -NOLOGO -EXTRACT:"$file" "$archive" || exit $?
|
||||
;;
|
||||
esac
|
||||
done
|
||||
else
|
||||
$AR -NOLOGO -LIST "$archive" | sed -e 's/\\/\\\\/g' | while read member
|
||||
do
|
||||
$AR -NOLOGO -EXTRACT:"$member" "$archive" || exit $?
|
||||
done
|
||||
fi
|
||||
|
||||
elif test -n "$quick$replace"; then
|
||||
if test ! -f "$orig_archive"; then
|
||||
if test -z "$create"; then
|
||||
echo "$me: creating $orig_archive"
|
||||
fi
|
||||
orig_archive=
|
||||
else
|
||||
orig_archive=$archive
|
||||
fi
|
||||
|
||||
for member
|
||||
do
|
||||
case $1 in
|
||||
@*)
|
||||
func_file_conv "${1#@}"
|
||||
set x "$@" "@$file"
|
||||
;;
|
||||
*)
|
||||
func_file_conv "$1"
|
||||
set x "$@" "$file"
|
||||
;;
|
||||
esac
|
||||
shift
|
||||
shift
|
||||
done
|
||||
|
||||
if test -n "$orig_archive"; then
|
||||
$AR -NOLOGO -OUT:"$archive" "$orig_archive" "$@" || exit $?
|
||||
else
|
||||
$AR -NOLOGO -OUT:"$archive" "$@" || exit $?
|
||||
fi
|
||||
|
||||
elif test -n "$list"; then
|
||||
if test ! -f "$orig_archive"; then
|
||||
func_error "archive not found"
|
||||
fi
|
||||
$AR -NOLOGO -LIST "$archive" || exit $?
|
||||
fi
|
|
@ -0,0 +1,150 @@
|
|||
tuple MachineExecutionEnvironment =
|
||||
Job_: Job
|
||||
IncludeDir_: String
|
||||
LibDir_: String
|
||||
LibMetal_: Path
|
||||
LibMetalGloss_: Path
|
||||
ConfigOptions: FreedomMetalConfigureOptions
|
||||
AllOutputs_: List Path
|
||||
|
||||
global def getMachineExecutionEnvironmentJob = getMachineExecutionEnvironmentJob_
|
||||
global def getMachineExecutionEnvironmentLibMetal = getMachineExecutionEnvironmentLibMetal_
|
||||
global def getMachineExecutionEnvironmentLibMetalGloss = getMachineExecutionEnvironmentLibMetalGloss_
|
||||
global def getMachineExecutionEnvironmentIncludeDir = getMachineExecutionEnvironmentIncludeDir_
|
||||
global def getMachineExecutionEnvironmentLibDir = getMachineExecutionEnvironmentLibDir_
|
||||
global def getMachineExecutionEnvironmentAllOutputs = getMachineExecutionEnvironmentAllOutputs_
|
||||
|
||||
global def getMachineExecutionEnvironmentRISCV_ARCH = _.getMachineExecutionEnvironmentConfigOptions.getFreedomMetalConfigureOptionsRISCV_ARCH
|
||||
global def getMachineExecutionEnvironmentRISCV_ABI = _.getMachineExecutionEnvironmentConfigOptions.getFreedomMetalConfigureOptionsRISCV_ABI
|
||||
global def getMachineExecutionEnvironmentRISCV_CMODEL = _.getMachineExecutionEnvironmentConfigOptions.getFreedomMetalConfigureOptionsRISCV_CMODEL
|
||||
global def getMachineExecutionEnvironmentHost = _.getMachineExecutionEnvironmentConfigOptions.getFreedomMetalConfigureOptionsHost
|
||||
global def getMachineExecutionEnvironmentPrefix = _.getMachineExecutionEnvironmentConfigOptions.getFreedomMetalConfigureOptionsOutputDir
|
||||
global def getMachineExecutionEnvironmentName = _.getMachineExecutionEnvironmentConfigOptions.getFreedomMetalConfigureOptionsMachineName
|
||||
global def getMachineExecutionEnvironmentHeader = _.getMachineExecutionEnvironmentConfigOptions.getFreedomMetalConfigureOptionsMachineHeader
|
||||
global def getMachineExecutionEnvironmentLdScript = _.getMachineExecutionEnvironmentConfigOptions.getFreedomMetalConfigureOptionsMachineLdScript
|
||||
|
||||
tuple FreedomMetalConfigureOptions =
|
||||
global Resources: List String
|
||||
global RISCV_ARCH: String
|
||||
global RISCV_ABI: String
|
||||
global RISCV_CMODEL: String
|
||||
global Host: String
|
||||
global OutputDir: String
|
||||
global MachineName: String
|
||||
global MachineHeader: Path
|
||||
global MachineInlineHeader: Path
|
||||
global PlatformHeader: Path
|
||||
global MachineLdScript: Path
|
||||
|
||||
global def defaultSiFiveRISCVResources = "riscv-tools/2019.05.0", Nil
|
||||
|
||||
global def makeFreedomMetalConfigureOptions arch abi cmodel host outputDir name header inlineHeader platformHeader ldScript =
|
||||
def resources = defaultSiFiveRISCVResources
|
||||
FreedomMetalConfigureOptions resources arch abi cmodel host outputDir name header inlineHeader platformHeader ldScript
|
||||
|
||||
global tuple MakeElfOptions =
|
||||
global MEE: MachineExecutionEnvironment
|
||||
global ProgramSrcs: List Path
|
||||
global CFlags: List String
|
||||
global LFlags: List String
|
||||
global IncludeDirs: List String
|
||||
global ElfFile: String
|
||||
|
||||
global def runFreedomMetalInstall options =
|
||||
def outputDir = options.getFreedomMetalConfigureOptionsOutputDir
|
||||
def metalHeader = options.getFreedomMetalConfigureOptionsMachineHeader
|
||||
def metalInline = options.getFreedomMetalConfigureOptionsMachineInlineHeader
|
||||
def platformHeader = options.getFreedomMetalConfigureOptionsPlatformHeader
|
||||
|
||||
def metalInstallDir = outputDir
|
||||
|
||||
def installedFreedomMetal =
|
||||
def inputs =
|
||||
sources "freedom-metal" `.*`
|
||||
| filter (!matches `freedom-metal/doc/.*` _.getPathName)
|
||||
def cmdline =
|
||||
"rsync",
|
||||
"-r",
|
||||
"--exclude", "freedom-metal/doc",
|
||||
"--exclude", "freedom-metal/.git",
|
||||
"--exclude", "*.wake",
|
||||
"freedom-metal",
|
||||
outputDir,
|
||||
Nil
|
||||
def fnOutputs _ =
|
||||
files "freedom-metal" `.*`
|
||||
| filter (!matches `freedom-metal/(\.git|doc)/.*` _)
|
||||
| filter (!matches `.*\.(in|am|m4|wake)` _) # exclude these because autoconf modfies them
|
||||
| filter (!matches `(.*/)?(configure)` _)
|
||||
| map ("{metalInstallDir}/{_}")
|
||||
|
||||
makePlan cmdline inputs
|
||||
| setPlanFnOutputs fnOutputs
|
||||
| setPlanLocalOnly True
|
||||
| runJob
|
||||
| getJobOutputs
|
||||
|
||||
|
||||
def runDir = "{metalInstallDir}/freedom-metal"
|
||||
def cmdline = "bash", "-c", "%
|
||||
set -eo pipefail
|
||||
machine_header=$(pwd)/%{metalHeader.getPathName}
|
||||
machine_inline=$(pwd)/%{metalInline.getPathName}
|
||||
platform_header=$(pwd)/%{platformHeader.getPathName}
|
||||
install_dir=$(pwd)/%{outputDir}
|
||||
export RISCV_PATH=$RISCV
|
||||
cd %{runDir}
|
||||
./configure \
|
||||
--host=%{options.getFreedomMetalConfigureOptionsHost} \
|
||||
--with-builtin-libgloss \
|
||||
--with-machine-header=$machine_header \
|
||||
--with-machine-inline=$machine_inline \
|
||||
--with-platform-header=$platform_header \
|
||||
--prefix=
|
||||
make \
|
||||
RANLIB="riscv64-unknown-elf-ranlib -D" \
|
||||
ARFLAGS=Dcr
|
||||
make \
|
||||
RANLIB="riscv64-unknown-elf-ranlib -D" \
|
||||
ARFLAGS=Dcr \
|
||||
DESTDIR=$install_dir \
|
||||
install
|
||||
%", Nil
|
||||
|
||||
def inputs = mkdir outputDir, metalHeader, installedFreedomMetal
|
||||
def foutputs _ =
|
||||
files "{outputDir}/include" `.*`
|
||||
++ files "{outputDir}/lib" `.*`
|
||||
def withCFlags =
|
||||
def march = options.getFreedomMetalConfigureOptionsRISCV_ARCH
|
||||
def mabi = options.getFreedomMetalConfigureOptionsRISCV_ABI
|
||||
def cmodel = options.getFreedomMetalConfigureOptionsRISCV_CMODEL
|
||||
"CFLAGS=-march={march} -mabi={mabi} -g -mcmodel={cmodel}", _
|
||||
|
||||
def job =
|
||||
makePlan cmdline inputs
|
||||
| setPlanLocalOnly True
|
||||
| setPlanFnOutputs foutputs
|
||||
| setPlanResources options.getFreedomMetalConfigureOptionsResources
|
||||
| editPlanEnvironment withCFlags
|
||||
| runJob
|
||||
def makeOutputs = job.getJobOutputs
|
||||
|
||||
def getFile f msg = match (makeOutputs | map getPathResult | findFail)
|
||||
Fail e = makeBadPath e
|
||||
Pass _ =
|
||||
filter (simplify f ==~ _.getPathName) makeOutputs
|
||||
| head
|
||||
| getOrElse msg.makeError.makeBadPath
|
||||
|
||||
def libmetal =
|
||||
def fileName = "{outputDir}/lib/libmetal.a"
|
||||
getFile fileName "Failed to compile libmetal: {fileName}"
|
||||
|
||||
def libmetalGloss =
|
||||
def fileName = "{outputDir}/lib/libmetal-gloss.a"
|
||||
getFile fileName "Failed to compile libgloss: {fileName}"
|
||||
|
||||
def includeDir = "{outputDir}/include"
|
||||
def libDir = "{outputDir}/lib"
|
||||
MachineExecutionEnvironment job includeDir libDir libmetal libmetalGloss options makeOutputs
|
|
@ -0,0 +1,347 @@
|
|||
#! /bin/sh
|
||||
# Wrapper for compilers which do not understand '-c -o'.
|
||||
|
||||
scriptversion=2012-10-14.11; # UTC
|
||||
|
||||
# Copyright (C) 1999-2014 Free Software Foundation, Inc.
|
||||
# Written by Tom Tromey <tromey@cygnus.com>.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2, or (at your option)
|
||||
# any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
# As a special exception to the GNU General Public License, if you
|
||||
# distribute this file as part of a program that contains a
|
||||
# configuration script generated by Autoconf, you may include it under
|
||||
# the same distribution terms that you use for the rest of that program.
|
||||
|
||||
# This file is maintained in Automake, please report
|
||||
# bugs to <bug-automake@gnu.org> or send patches to
|
||||
# <automake-patches@gnu.org>.
|
||||
|
||||
nl='
|
||||
'
|
||||
|
||||
# We need space, tab and new line, in precisely that order. Quoting is
|
||||
# there to prevent tools from complaining about whitespace usage.
|
||||
IFS=" "" $nl"
|
||||
|
||||
file_conv=
|
||||
|
||||
# func_file_conv build_file lazy
|
||||
# Convert a $build file to $host form and store it in $file
|
||||
# Currently only supports Windows hosts. If the determined conversion
|
||||
# type is listed in (the comma separated) LAZY, no conversion will
|
||||
# take place.
|
||||
func_file_conv ()
|
||||
{
|
||||
file=$1
|
||||
case $file in
|
||||
/ | /[!/]*) # absolute file, and not a UNC file
|
||||
if test -z "$file_conv"; then
|
||||
# lazily determine how to convert abs files
|
||||
case `uname -s` in
|
||||
MINGW*)
|
||||
file_conv=mingw
|
||||
;;
|
||||
CYGWIN*)
|
||||
file_conv=cygwin
|
||||
;;
|
||||
*)
|
||||
file_conv=wine
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
case $file_conv/,$2, in
|
||||
*,$file_conv,*)
|
||||
;;
|
||||
mingw/*)
|
||||
file=`cmd //C echo "$file " | sed -e 's/"\(.*\) " *$/\1/'`
|
||||
;;
|
||||
cygwin/*)
|
||||
file=`cygpath -m "$file" || echo "$file"`
|
||||
;;
|
||||
wine/*)
|
||||
file=`winepath -w "$file" || echo "$file"`
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
# func_cl_dashL linkdir
|
||||
# Make cl look for libraries in LINKDIR
|
||||
func_cl_dashL ()
|
||||
{
|
||||
func_file_conv "$1"
|
||||
if test -z "$lib_path"; then
|
||||
lib_path=$file
|
||||
else
|
||||
lib_path="$lib_path;$file"
|
||||
fi
|
||||
linker_opts="$linker_opts -LIBPATH:$file"
|
||||
}
|
||||
|
||||
# func_cl_dashl library
|
||||
# Do a library search-path lookup for cl
|
||||
func_cl_dashl ()
|
||||
{
|
||||
lib=$1
|
||||
found=no
|
||||
save_IFS=$IFS
|
||||
IFS=';'
|
||||
for dir in $lib_path $LIB
|
||||
do
|
||||
IFS=$save_IFS
|
||||
if $shared && test -f "$dir/$lib.dll.lib"; then
|
||||
found=yes
|
||||
lib=$dir/$lib.dll.lib
|
||||
break
|
||||
fi
|
||||
if test -f "$dir/$lib.lib"; then
|
||||
found=yes
|
||||
lib=$dir/$lib.lib
|
||||
break
|
||||
fi
|
||||
if test -f "$dir/lib$lib.a"; then
|
||||
found=yes
|
||||
lib=$dir/lib$lib.a
|
||||
break
|
||||
fi
|
||||
done
|
||||
IFS=$save_IFS
|
||||
|
||||
if test "$found" != yes; then
|
||||
lib=$lib.lib
|
||||
fi
|
||||
}
|
||||
|
||||
# func_cl_wrapper cl arg...
|
||||
# Adjust compile command to suit cl
|
||||
func_cl_wrapper ()
|
||||
{
|
||||
# Assume a capable shell
|
||||
lib_path=
|
||||
shared=:
|
||||
linker_opts=
|
||||
for arg
|
||||
do
|
||||
if test -n "$eat"; then
|
||||
eat=
|
||||
else
|
||||
case $1 in
|
||||
-o)
|
||||
# configure might choose to run compile as 'compile cc -o foo foo.c'.
|
||||
eat=1
|
||||
case $2 in
|
||||
*.o | *.[oO][bB][jJ])
|
||||
func_file_conv "$2"
|
||||
set x "$@" -Fo"$file"
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
func_file_conv "$2"
|
||||
set x "$@" -Fe"$file"
|
||||
shift
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
-I)
|
||||
eat=1
|
||||
func_file_conv "$2" mingw
|
||||
set x "$@" -I"$file"
|
||||
shift
|
||||
;;
|
||||
-I*)
|
||||
func_file_conv "${1#-I}" mingw
|
||||
set x "$@" -I"$file"
|
||||
shift
|
||||
;;
|
||||
-l)
|
||||
eat=1
|
||||
func_cl_dashl "$2"
|
||||
set x "$@" "$lib"
|
||||
shift
|
||||
;;
|
||||
-l*)
|
||||
func_cl_dashl "${1#-l}"
|
||||
set x "$@" "$lib"
|
||||
shift
|
||||
;;
|
||||
-L)
|
||||
eat=1
|
||||
func_cl_dashL "$2"
|
||||
;;
|
||||
-L*)
|
||||
func_cl_dashL "${1#-L}"
|
||||
;;
|
||||
-static)
|
||||
shared=false
|
||||
;;
|
||||
-Wl,*)
|
||||
arg=${1#-Wl,}
|
||||
save_ifs="$IFS"; IFS=','
|
||||
for flag in $arg; do
|
||||
IFS="$save_ifs"
|
||||
linker_opts="$linker_opts $flag"
|
||||
done
|
||||
IFS="$save_ifs"
|
||||
;;
|
||||
-Xlinker)
|
||||
eat=1
|
||||
linker_opts="$linker_opts $2"
|
||||
;;
|
||||
-*)
|
||||
set x "$@" "$1"
|
||||
shift
|
||||
;;
|
||||
*.cc | *.CC | *.cxx | *.CXX | *.[cC]++)
|
||||
func_file_conv "$1"
|
||||
set x "$@" -Tp"$file"
|
||||
shift
|
||||
;;
|
||||
*.c | *.cpp | *.CPP | *.lib | *.LIB | *.Lib | *.OBJ | *.obj | *.[oO])
|
||||
func_file_conv "$1" mingw
|
||||
set x "$@" "$file"
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
set x "$@" "$1"
|
||||
shift
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
shift
|
||||
done
|
||||
if test -n "$linker_opts"; then
|
||||
linker_opts="-link$linker_opts"
|
||||
fi
|
||||
exec "$@" $linker_opts
|
||||
exit 1
|
||||
}
|
||||
|
||||
eat=
|
||||
|
||||
case $1 in
|
||||
'')
|
||||
echo "$0: No command. Try '$0 --help' for more information." 1>&2
|
||||
exit 1;
|
||||
;;
|
||||
-h | --h*)
|
||||
cat <<\EOF
|
||||
Usage: compile [--help] [--version] PROGRAM [ARGS]
|
||||
|
||||
Wrapper for compilers which do not understand '-c -o'.
|
||||
Remove '-o dest.o' from ARGS, run PROGRAM with the remaining
|
||||
arguments, and rename the output as expected.
|
||||
|
||||
If you are trying to build a whole package this is not the
|
||||
right script to run: please start by reading the file 'INSTALL'.
|
||||
|
||||
Report bugs to <bug-automake@gnu.org>.
|
||||
EOF
|
||||
exit $?
|
||||
;;
|
||||
-v | --v*)
|
||||
echo "compile $scriptversion"
|
||||
exit $?
|
||||
;;
|
||||
cl | *[/\\]cl | cl.exe | *[/\\]cl.exe )
|
||||
func_cl_wrapper "$@" # Doesn't return...
|
||||
;;
|
||||
esac
|
||||
|
||||
ofile=
|
||||
cfile=
|
||||
|
||||
for arg
|
||||
do
|
||||
if test -n "$eat"; then
|
||||
eat=
|
||||
else
|
||||
case $1 in
|
||||
-o)
|
||||
# configure might choose to run compile as 'compile cc -o foo foo.c'.
|
||||
# So we strip '-o arg' only if arg is an object.
|
||||
eat=1
|
||||
case $2 in
|
||||
*.o | *.obj)
|
||||
ofile=$2
|
||||
;;
|
||||
*)
|
||||
set x "$@" -o "$2"
|
||||
shift
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
*.c)
|
||||
cfile=$1
|
||||
set x "$@" "$1"
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
set x "$@" "$1"
|
||||
shift
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
shift
|
||||
done
|
||||
|
||||
if test -z "$ofile" || test -z "$cfile"; then
|
||||
# If no '-o' option was seen then we might have been invoked from a
|
||||
# pattern rule where we don't need one. That is ok -- this is a
|
||||
# normal compilation that the losing compiler can handle. If no
|
||||
# '.c' file was seen then we are probably linking. That is also
|
||||
# ok.
|
||||
exec "$@"
|
||||
fi
|
||||
|
||||
# Name of file we expect compiler to create.
|
||||
cofile=`echo "$cfile" | sed 's|^.*[\\/]||; s|^[a-zA-Z]:||; s/\.c$/.o/'`
|
||||
|
||||
# Create the lock directory.
|
||||
# Note: use '[/\\:.-]' here to ensure that we don't use the same name
|
||||
# that we are using for the .o file. Also, base the name on the expected
|
||||
# object file name, since that is what matters with a parallel build.
|
||||
lockdir=`echo "$cofile" | sed -e 's|[/\\:.-]|_|g'`.d
|
||||
while true; do
|
||||
if mkdir "$lockdir" >/dev/null 2>&1; then
|
||||
break
|
||||
fi
|
||||
sleep 1
|
||||
done
|
||||
# FIXME: race condition here if user kills between mkdir and trap.
|
||||
trap "rmdir '$lockdir'; exit 1" 1 2 15
|
||||
|
||||
# Run the compile.
|
||||
"$@"
|
||||
ret=$?
|
||||
|
||||
if test -f "$cofile"; then
|
||||
test "$cofile" = "$ofile" || mv "$cofile" "$ofile"
|
||||
elif test -f "${cofile}bj"; then
|
||||
test "${cofile}bj" = "$ofile" || mv "${cofile}bj" "$ofile"
|
||||
fi
|
||||
|
||||
rmdir "$lockdir"
|
||||
exit $ret
|
||||
|
||||
# Local Variables:
|
||||
# mode: shell-script
|
||||
# sh-indentation: 2
|
||||
# eval: (add-hook 'write-file-hooks 'time-stamp)
|
||||
# time-stamp-start: "scriptversion="
|
||||
# time-stamp-format: "%:y-%02m-%02d.%02H"
|
||||
# time-stamp-time-zone: "UTC"
|
||||
# time-stamp-end: "; # UTC"
|
||||
# End:
|
1441
FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/config.guess
vendored
Executable file
1441
FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/config.guess
vendored
Executable file
File diff suppressed because it is too large
Load diff
1813
FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/config.sub
vendored
Executable file
1813
FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/config.sub
vendored
Executable file
File diff suppressed because it is too large
Load diff
5491
FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/configure
vendored
Executable file
5491
FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/configure
vendored
Executable file
File diff suppressed because it is too large
Load diff
|
@ -0,0 +1,97 @@
|
|||
# The name, version, and maintainer of this package
|
||||
AC_INIT([freedom-metal], [m4_esyscmd_s([./scripts/git-version])], [https://github.com/sifive/freedom-metal/issues], [freedom-metal], [https://github.com/sifive/freedom-metal])
|
||||
|
||||
# Initializes automake, enabling maintainer mode by default (which should be
|
||||
# disabled by the archive generated by "make dist").
|
||||
AM_INIT_AUTOMAKE([foreign subdir-objects])
|
||||
AM_MAINTAINER_MODE([disable])
|
||||
AC_CONFIG_MACRO_DIRS([m4])
|
||||
|
||||
AC_CANONICAL_HOST
|
||||
|
||||
# Probe for tools that we need in order to build.
|
||||
AC_PROG_CC
|
||||
AC_PROG_RANLIB
|
||||
AM_PROG_AR
|
||||
AM_PROG_AS
|
||||
|
||||
# autoconf tries very hard to avoid failing, so it'll even go ahead and try to
|
||||
# build the project using "gcc" if it can't find a suitable C compiler prefixed
|
||||
# by the host system. This doesn't work when cross compiling, but it's a
|
||||
# common error for users so we explicitly check for this right here to quickly
|
||||
# provide an error message.
|
||||
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([],[
|
||||
#ifndef __riscv
|
||||
# error "A RISC-V compiler is required to build Freedom Metal"
|
||||
#endif
|
||||
])], [], [AC_MSG_FAILURE([The C compiler doesn't define __riscv, which means it's probably not a RISC-V compiler. You should specify something like --host=riscv64-sifive-elf when building this, as it will only work on RISC-V systems.])])
|
||||
|
||||
########################################################
|
||||
# Options
|
||||
########################################################
|
||||
|
||||
AC_ARG_WITH([builtin-libgloss],
|
||||
[AS_HELP_STRING([--with-bultin-libgloss], [Build libgloss along with Metal])],
|
||||
[with_builtin_libgloss="yes"],
|
||||
[with_builtin_libgloss="no"]
|
||||
)
|
||||
|
||||
AC_ARG_WITH([builtin-libmetal-pico],
|
||||
[AS_HELP_STRING([--with-bultin-libmetal-pico], [Build libmetal-pico along with Metal])],
|
||||
[with_builtin_libmetal_pico="yes"],
|
||||
[with_builtin_libmetal_pico="no"]
|
||||
)
|
||||
|
||||
AC_ARG_WITH([builtin-libmetal-segger],
|
||||
[AS_HELP_STRING([--with-bultin-libmetal-segger], [Build libmetal-segger along with Metal])],
|
||||
[with_builtin_libmetal_segger="yes"],
|
||||
[with_builtin_libmetal_segger="no"]
|
||||
)
|
||||
|
||||
AC_ARG_WITH([machine-header],
|
||||
[AS_HELP_STRING([--with-machine-header=PATH], [Path to the machine header file])],
|
||||
[],
|
||||
[with_machine_header="no"]
|
||||
)
|
||||
|
||||
AC_ARG_WITH([machine-inline],
|
||||
[AS_HELP_STRING([--with-machine-inline=PATH], [Path to the machine inline file])],
|
||||
[],
|
||||
[with_machine_inline="no"]
|
||||
)
|
||||
|
||||
AC_ARG_WITH([platform-header],
|
||||
[AS_HELP_STRING([--with-platform-header=PATH], [Path to the platform header file])],
|
||||
[],
|
||||
[with_platform_header="no"]
|
||||
)
|
||||
|
||||
########################################################
|
||||
# Process Options
|
||||
########################################################
|
||||
|
||||
AM_CONDITIONAL([WITH_BUILTIN_LIBGLOSS], [test "x$with_builtin_libgloss" = "xyes"])
|
||||
|
||||
AM_CONDITIONAL([WITH_BUILTIN_LIBMETAL_PICO], [test "x$with_builtin_libmetal_pico" = "xyes"])
|
||||
|
||||
AM_CONDITIONAL([WITH_BUILTIN_LIBMETAL_SEGGER], [test "x$with_builtin_libmetal_segger" = "xyes"])
|
||||
|
||||
# Configure the build system to pass in the preconfigured machine support files
|
||||
AS_IF([test "x$with_machine_header" != "xno"],
|
||||
[AC_SUBST([MACHINE_HEADER], "$with_machine_header")],
|
||||
[AC_MSG_FAILURE([--with-machine-header is required])]
|
||||
)
|
||||
|
||||
AS_IF([test "x$with_machine_inline" != "xno"],
|
||||
[AC_SUBST([MACHINE_INLINE], "$with_machine_inline")],
|
||||
[AC_MSG_FAILURE([--with-machine-inline is required])]
|
||||
)
|
||||
|
||||
AS_IF([test "x$with_platform_header" != "xno"],
|
||||
[AC_SUBST([PLATFORM_HEADER], "$with_platform_header")],
|
||||
[AC_MSG_FAILURE([--with-platform-header is required])]
|
||||
)
|
||||
|
||||
# Generates the remainder of the build system.
|
||||
AC_CONFIG_FILES([Makefile])
|
||||
AC_OUTPUT
|
|
@ -0,0 +1,791 @@
|
|||
#! /bin/sh
|
||||
# depcomp - compile a program generating dependencies as side-effects
|
||||
|
||||
scriptversion=2013-05-30.07; # UTC
|
||||
|
||||
# Copyright (C) 1999-2014 Free Software Foundation, Inc.
|
||||
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2, or (at your option)
|
||||
# any later version.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
# As a special exception to the GNU General Public License, if you
|
||||
# distribute this file as part of a program that contains a
|
||||
# configuration script generated by Autoconf, you may include it under
|
||||
# the same distribution terms that you use for the rest of that program.
|
||||
|
||||
# Originally written by Alexandre Oliva <oliva@dcc.unicamp.br>.
|
||||
|
||||
case $1 in
|
||||
'')
|
||||
echo "$0: No command. Try '$0 --help' for more information." 1>&2
|
||||
exit 1;
|
||||
;;
|
||||
-h | --h*)
|
||||
cat <<\EOF
|
||||
Usage: depcomp [--help] [--version] PROGRAM [ARGS]
|
||||
|
||||
Run PROGRAMS ARGS to compile a file, generating dependencies
|
||||
as side-effects.
|
||||
|
||||
Environment variables:
|
||||
depmode Dependency tracking mode.
|
||||
source Source file read by 'PROGRAMS ARGS'.
|
||||
object Object file output by 'PROGRAMS ARGS'.
|
||||
DEPDIR directory where to store dependencies.
|
||||
depfile Dependency file to output.
|
||||
tmpdepfile Temporary file to use when outputting dependencies.
|
||||
libtool Whether libtool is used (yes/no).
|
||||
|
||||
Report bugs to <bug-automake@gnu.org>.
|
||||
EOF
|
||||
exit $?
|
||||
;;
|
||||
-v | --v*)
|
||||
echo "depcomp $scriptversion"
|
||||
exit $?
|
||||
;;
|
||||
esac
|
||||
|
||||
# Get the directory component of the given path, and save it in the
|
||||
# global variables '$dir'. Note that this directory component will
|
||||
# be either empty or ending with a '/' character. This is deliberate.
|
||||
set_dir_from ()
|
||||
{
|
||||
case $1 in
|
||||
*/*) dir=`echo "$1" | sed -e 's|/[^/]*$|/|'`;;
|
||||
*) dir=;;
|
||||
esac
|
||||
}
|
||||
|
||||
# Get the suffix-stripped basename of the given path, and save it the
|
||||
# global variable '$base'.
|
||||
set_base_from ()
|
||||
{
|
||||
base=`echo "$1" | sed -e 's|^.*/||' -e 's/\.[^.]*$//'`
|
||||
}
|
||||
|
||||
# If no dependency file was actually created by the compiler invocation,
|
||||
# we still have to create a dummy depfile, to avoid errors with the
|
||||
# Makefile "include basename.Plo" scheme.
|
||||
make_dummy_depfile ()
|
||||
{
|
||||
echo "#dummy" > "$depfile"
|
||||
}
|
||||
|
||||
# Factor out some common post-processing of the generated depfile.
|
||||
# Requires the auxiliary global variable '$tmpdepfile' to be set.
|
||||
aix_post_process_depfile ()
|
||||
{
|
||||
# If the compiler actually managed to produce a dependency file,
|
||||
# post-process it.
|
||||
if test -f "$tmpdepfile"; then
|
||||
# Each line is of the form 'foo.o: dependency.h'.
|
||||
# Do two passes, one to just change these to
|
||||
# $object: dependency.h
|
||||
# and one to simply output
|
||||
# dependency.h:
|
||||
# which is needed to avoid the deleted-header problem.
|
||||
{ sed -e "s,^.*\.[$lower]*:,$object:," < "$tmpdepfile"
|
||||
sed -e "s,^.*\.[$lower]*:[$tab ]*,," -e 's,$,:,' < "$tmpdepfile"
|
||||
} > "$depfile"
|
||||
rm -f "$tmpdepfile"
|
||||
else
|
||||
make_dummy_depfile
|
||||
fi
|
||||
}
|
||||
|
||||
# A tabulation character.
|
||||
tab=' '
|
||||
# A newline character.
|
||||
nl='
|
||||
'
|
||||
# Character ranges might be problematic outside the C locale.
|
||||
# These definitions help.
|
||||
upper=ABCDEFGHIJKLMNOPQRSTUVWXYZ
|
||||
lower=abcdefghijklmnopqrstuvwxyz
|
||||
digits=0123456789
|
||||
alpha=${upper}${lower}
|
||||
|
||||
if test -z "$depmode" || test -z "$source" || test -z "$object"; then
|
||||
echo "depcomp: Variables source, object and depmode must be set" 1>&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Dependencies for sub/bar.o or sub/bar.obj go into sub/.deps/bar.Po.
|
||||
depfile=${depfile-`echo "$object" |
|
||||
sed 's|[^\\/]*$|'${DEPDIR-.deps}'/&|;s|\.\([^.]*\)$|.P\1|;s|Pobj$|Po|'`}
|
||||
tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`}
|
||||
|
||||
rm -f "$tmpdepfile"
|
||||
|
||||
# Avoid interferences from the environment.
|
||||
gccflag= dashmflag=
|
||||
|
||||
# Some modes work just like other modes, but use different flags. We
|
||||
# parameterize here, but still list the modes in the big case below,
|
||||
# to make depend.m4 easier to write. Note that we *cannot* use a case
|
||||
# here, because this file can only contain one case statement.
|
||||
if test "$depmode" = hp; then
|
||||
# HP compiler uses -M and no extra arg.
|
||||
gccflag=-M
|
||||
depmode=gcc
|
||||
fi
|
||||
|
||||
if test "$depmode" = dashXmstdout; then
|
||||
# This is just like dashmstdout with a different argument.
|
||||
dashmflag=-xM
|
||||
depmode=dashmstdout
|
||||
fi
|
||||
|
||||
cygpath_u="cygpath -u -f -"
|
||||
if test "$depmode" = msvcmsys; then
|
||||
# This is just like msvisualcpp but w/o cygpath translation.
|
||||
# Just convert the backslash-escaped backslashes to single forward
|
||||
# slashes to satisfy depend.m4
|
||||
cygpath_u='sed s,\\\\,/,g'
|
||||
depmode=msvisualcpp
|
||||
fi
|
||||
|
||||
if test "$depmode" = msvc7msys; then
|
||||
# This is just like msvc7 but w/o cygpath translation.
|
||||
# Just convert the backslash-escaped backslashes to single forward
|
||||
# slashes to satisfy depend.m4
|
||||
cygpath_u='sed s,\\\\,/,g'
|
||||
depmode=msvc7
|
||||
fi
|
||||
|
||||
if test "$depmode" = xlc; then
|
||||
# IBM C/C++ Compilers xlc/xlC can output gcc-like dependency information.
|
||||
gccflag=-qmakedep=gcc,-MF
|
||||
depmode=gcc
|
||||
fi
|
||||
|
||||
case "$depmode" in
|
||||
gcc3)
|
||||
## gcc 3 implements dependency tracking that does exactly what
|
||||
## we want. Yay! Note: for some reason libtool 1.4 doesn't like
|
||||
## it if -MD -MP comes after the -MF stuff. Hmm.
|
||||
## Unfortunately, FreeBSD c89 acceptance of flags depends upon
|
||||
## the command line argument order; so add the flags where they
|
||||
## appear in depend2.am. Note that the slowdown incurred here
|
||||
## affects only configure: in makefiles, %FASTDEP% shortcuts this.
|
||||
for arg
|
||||
do
|
||||
case $arg in
|
||||
-c) set fnord "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" "$arg" ;;
|
||||
*) set fnord "$@" "$arg" ;;
|
||||
esac
|
||||
shift # fnord
|
||||
shift # $arg
|
||||
done
|
||||
"$@"
|
||||
stat=$?
|
||||
if test $stat -ne 0; then
|
||||
rm -f "$tmpdepfile"
|
||||
exit $stat
|
||||
fi
|
||||
mv "$tmpdepfile" "$depfile"
|
||||
;;
|
||||
|
||||
gcc)
|
||||
## Note that this doesn't just cater to obsosete pre-3.x GCC compilers.
|
||||
## but also to in-use compilers like IMB xlc/xlC and the HP C compiler.
|
||||
## (see the conditional assignment to $gccflag above).
|
||||
## There are various ways to get dependency output from gcc. Here's
|
||||
## why we pick this rather obscure method:
|
||||
## - Don't want to use -MD because we'd like the dependencies to end
|
||||
## up in a subdir. Having to rename by hand is ugly.
|
||||
## (We might end up doing this anyway to support other compilers.)
|
||||
## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like
|
||||
## -MM, not -M (despite what the docs say). Also, it might not be
|
||||
## supported by the other compilers which use the 'gcc' depmode.
|
||||
## - Using -M directly means running the compiler twice (even worse
|
||||
## than renaming).
|
||||
if test -z "$gccflag"; then
|
||||
gccflag=-MD,
|
||||
fi
|
||||
"$@" -Wp,"$gccflag$tmpdepfile"
|
||||
stat=$?
|
||||
if test $stat -ne 0; then
|
||||
rm -f "$tmpdepfile"
|
||||
exit $stat
|
||||
fi
|
||||
rm -f "$depfile"
|
||||
echo "$object : \\" > "$depfile"
|
||||
# The second -e expression handles DOS-style file names with drive
|
||||
# letters.
|
||||
sed -e 's/^[^:]*: / /' \
|
||||
-e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile"
|
||||
## This next piece of magic avoids the "deleted header file" problem.
|
||||
## The problem is that when a header file which appears in a .P file
|
||||
## is deleted, the dependency causes make to die (because there is
|
||||
## typically no way to rebuild the header). We avoid this by adding
|
||||
## dummy dependencies for each header file. Too bad gcc doesn't do
|
||||
## this for us directly.
|
||||
## Some versions of gcc put a space before the ':'. On the theory
|
||||
## that the space means something, we add a space to the output as
|
||||
## well. hp depmode also adds that space, but also prefixes the VPATH
|
||||
## to the object. Take care to not repeat it in the output.
|
||||
## Some versions of the HPUX 10.20 sed can't process this invocation
|
||||
## correctly. Breaking it into two sed invocations is a workaround.
|
||||
tr ' ' "$nl" < "$tmpdepfile" \
|
||||
| sed -e 's/^\\$//' -e '/^$/d' -e "s|.*$object$||" -e '/:$/d' \
|
||||
| sed -e 's/$/ :/' >> "$depfile"
|
||||
rm -f "$tmpdepfile"
|
||||
;;
|
||||
|
||||
hp)
|
||||
# This case exists only to let depend.m4 do its work. It works by
|
||||
# looking at the text of this script. This case will never be run,
|
||||
# since it is checked for above.
|
||||
exit 1
|
||||
;;
|
||||
|
||||
sgi)
|
||||
if test "$libtool" = yes; then
|
||||
"$@" "-Wp,-MDupdate,$tmpdepfile"
|
||||
else
|
||||
"$@" -MDupdate "$tmpdepfile"
|
||||
fi
|
||||
stat=$?
|
||||
if test $stat -ne 0; then
|
||||
rm -f "$tmpdepfile"
|
||||
exit $stat
|
||||
fi
|
||||
rm -f "$depfile"
|
||||
|
||||
if test -f "$tmpdepfile"; then # yes, the sourcefile depend on other files
|
||||
echo "$object : \\" > "$depfile"
|
||||
# Clip off the initial element (the dependent). Don't try to be
|
||||
# clever and replace this with sed code, as IRIX sed won't handle
|
||||
# lines with more than a fixed number of characters (4096 in
|
||||
# IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines;
|
||||
# the IRIX cc adds comments like '#:fec' to the end of the
|
||||
# dependency line.
|
||||
tr ' ' "$nl" < "$tmpdepfile" \
|
||||
| sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' \
|
||||
| tr "$nl" ' ' >> "$depfile"
|
||||
echo >> "$depfile"
|
||||
# The second pass generates a dummy entry for each header file.
|
||||
tr ' ' "$nl" < "$tmpdepfile" \
|
||||
| sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \
|
||||
>> "$depfile"
|
||||
else
|
||||
make_dummy_depfile
|
||||
fi
|
||||
rm -f "$tmpdepfile"
|
||||
;;
|
||||
|
||||
xlc)
|
||||
# This case exists only to let depend.m4 do its work. It works by
|
||||
# looking at the text of this script. This case will never be run,
|
||||
# since it is checked for above.
|
||||
exit 1
|
||||
;;
|
||||
|
||||
aix)
|
||||
# The C for AIX Compiler uses -M and outputs the dependencies
|
||||
# in a .u file. In older versions, this file always lives in the
|
||||
# current directory. Also, the AIX compiler puts '$object:' at the
|
||||
# start of each line; $object doesn't have directory information.
|
||||
# Version 6 uses the directory in both cases.
|
||||
set_dir_from "$object"
|
||||
set_base_from "$object"
|
||||
if test "$libtool" = yes; then
|
||||
tmpdepfile1=$dir$base.u
|
||||
tmpdepfile2=$base.u
|
||||
tmpdepfile3=$dir.libs/$base.u
|
||||
"$@" -Wc,-M
|
||||
else
|
||||
tmpdepfile1=$dir$base.u
|
||||
tmpdepfile2=$dir$base.u
|
||||
tmpdepfile3=$dir$base.u
|
||||
"$@" -M
|
||||
fi
|
||||
stat=$?
|
||||
if test $stat -ne 0; then
|
||||
rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
|
||||
exit $stat
|
||||
fi
|
||||
|
||||
for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
|
||||
do
|
||||
test -f "$tmpdepfile" && break
|
||||
done
|
||||
aix_post_process_depfile
|
||||
;;
|
||||
|
||||
tcc)
|
||||
# tcc (Tiny C Compiler) understand '-MD -MF file' since version 0.9.26
|
||||
# FIXME: That version still under development at the moment of writing.
|
||||
# Make that this statement remains true also for stable, released
|
||||
# versions.
|
||||
# It will wrap lines (doesn't matter whether long or short) with a
|
||||
# trailing '\', as in:
|
||||
#
|
||||
# foo.o : \
|
||||
# foo.c \
|
||||
# foo.h \
|
||||
#
|
||||
# It will put a trailing '\' even on the last line, and will use leading
|
||||
# spaces rather than leading tabs (at least since its commit 0394caf7
|
||||
# "Emit spaces for -MD").
|
||||
"$@" -MD -MF "$tmpdepfile"
|
||||
stat=$?
|
||||
if test $stat -ne 0; then
|
||||
rm -f "$tmpdepfile"
|
||||
exit $stat
|
||||
fi
|
||||
rm -f "$depfile"
|
||||
# Each non-empty line is of the form 'foo.o : \' or ' dep.h \'.
|
||||
# We have to change lines of the first kind to '$object: \'.
|
||||
sed -e "s|.*:|$object :|" < "$tmpdepfile" > "$depfile"
|
||||
# And for each line of the second kind, we have to emit a 'dep.h:'
|
||||
# dummy dependency, to avoid the deleted-header problem.
|
||||
sed -n -e 's|^ *\(.*\) *\\$|\1:|p' < "$tmpdepfile" >> "$depfile"
|
||||
rm -f "$tmpdepfile"
|
||||
;;
|
||||
|
||||
## The order of this option in the case statement is important, since the
|
||||
## shell code in configure will try each of these formats in the order
|
||||
## listed in this file. A plain '-MD' option would be understood by many
|
||||
## compilers, so we must ensure this comes after the gcc and icc options.
|
||||
pgcc)
|
||||
# Portland's C compiler understands '-MD'.
|
||||
# Will always output deps to 'file.d' where file is the root name of the
|
||||
# source file under compilation, even if file resides in a subdirectory.
|
||||
# The object file name does not affect the name of the '.d' file.
|
||||
# pgcc 10.2 will output
|
||||
# foo.o: sub/foo.c sub/foo.h
|
||||
# and will wrap long lines using '\' :
|
||||
# foo.o: sub/foo.c ... \
|
||||
# sub/foo.h ... \
|
||||
# ...
|
||||
set_dir_from "$object"
|
||||
# Use the source, not the object, to determine the base name, since
|
||||
# that's sadly what pgcc will do too.
|
||||
set_base_from "$source"
|
||||
tmpdepfile=$base.d
|
||||
|
||||
# For projects that build the same source file twice into different object
|
||||
# files, the pgcc approach of using the *source* file root name can cause
|
||||
# problems in parallel builds. Use a locking strategy to avoid stomping on
|
||||
# the same $tmpdepfile.
|
||||
lockdir=$base.d-lock
|
||||
trap "
|
||||
echo '$0: caught signal, cleaning up...' >&2
|
||||
rmdir '$lockdir'
|
||||
exit 1
|
||||
" 1 2 13 15
|
||||
numtries=100
|
||||
i=$numtries
|
||||
while test $i -gt 0; do
|
||||
# mkdir is a portable test-and-set.
|
||||
if mkdir "$lockdir" 2>/dev/null; then
|
||||
# This process acquired the lock.
|
||||
"$@" -MD
|
||||
stat=$?
|
||||
# Release the lock.
|
||||
rmdir "$lockdir"
|
||||
break
|
||||
else
|
||||
# If the lock is being held by a different process, wait
|
||||
# until the winning process is done or we timeout.
|
||||
while test -d "$lockdir" && test $i -gt 0; do
|
||||
sleep 1
|
||||
i=`expr $i - 1`
|
||||
done
|
||||
fi
|
||||
i=`expr $i - 1`
|
||||
done
|
||||
trap - 1 2 13 15
|
||||
if test $i -le 0; then
|
||||
echo "$0: failed to acquire lock after $numtries attempts" >&2
|
||||
echo "$0: check lockdir '$lockdir'" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if test $stat -ne 0; then
|
||||
rm -f "$tmpdepfile"
|
||||
exit $stat
|
||||
fi
|
||||
rm -f "$depfile"
|
||||
# Each line is of the form `foo.o: dependent.h',
|
||||
# or `foo.o: dep1.h dep2.h \', or ` dep3.h dep4.h \'.
|
||||
# Do two passes, one to just change these to
|
||||
# `$object: dependent.h' and one to simply `dependent.h:'.
|
||||
sed "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile"
|
||||
# Some versions of the HPUX 10.20 sed can't process this invocation
|
||||
# correctly. Breaking it into two sed invocations is a workaround.
|
||||
sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" \
|
||||
| sed -e 's/$/ :/' >> "$depfile"
|
||||
rm -f "$tmpdepfile"
|
||||
;;
|
||||
|
||||
hp2)
|
||||
# The "hp" stanza above does not work with aCC (C++) and HP's ia64
|
||||
# compilers, which have integrated preprocessors. The correct option
|
||||
# to use with these is +Maked; it writes dependencies to a file named
|
||||
# 'foo.d', which lands next to the object file, wherever that
|
||||
# happens to be.
|
||||
# Much of this is similar to the tru64 case; see comments there.
|
||||
set_dir_from "$object"
|
||||
set_base_from "$object"
|
||||
if test "$libtool" = yes; then
|
||||
tmpdepfile1=$dir$base.d
|
||||
tmpdepfile2=$dir.libs/$base.d
|
||||
"$@" -Wc,+Maked
|
||||
else
|
||||
tmpdepfile1=$dir$base.d
|
||||
tmpdepfile2=$dir$base.d
|
||||
"$@" +Maked
|
||||
fi
|
||||
stat=$?
|
||||
if test $stat -ne 0; then
|
||||
rm -f "$tmpdepfile1" "$tmpdepfile2"
|
||||
exit $stat
|
||||
fi
|
||||
|
||||
for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2"
|
||||
do
|
||||
test -f "$tmpdepfile" && break
|
||||
done
|
||||
if test -f "$tmpdepfile"; then
|
||||
sed -e "s,^.*\.[$lower]*:,$object:," "$tmpdepfile" > "$depfile"
|
||||
# Add 'dependent.h:' lines.
|
||||
sed -ne '2,${
|
||||
s/^ *//
|
||||
s/ \\*$//
|
||||
s/$/:/
|
||||
p
|
||||
}' "$tmpdepfile" >> "$depfile"
|
||||
else
|
||||
make_dummy_depfile
|
||||
fi
|
||||
rm -f "$tmpdepfile" "$tmpdepfile2"
|
||||
;;
|
||||
|
||||
tru64)
|
||||
# The Tru64 compiler uses -MD to generate dependencies as a side
|
||||
# effect. 'cc -MD -o foo.o ...' puts the dependencies into 'foo.o.d'.
|
||||
# At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put
|
||||
# dependencies in 'foo.d' instead, so we check for that too.
|
||||
# Subdirectories are respected.
|
||||
set_dir_from "$object"
|
||||
set_base_from "$object"
|
||||
|
||||
if test "$libtool" = yes; then
|
||||
# Libtool generates 2 separate objects for the 2 libraries. These
|
||||
# two compilations output dependencies in $dir.libs/$base.o.d and
|
||||
# in $dir$base.o.d. We have to check for both files, because
|
||||
# one of the two compilations can be disabled. We should prefer
|
||||
# $dir$base.o.d over $dir.libs/$base.o.d because the latter is
|
||||
# automatically cleaned when .libs/ is deleted, while ignoring
|
||||
# the former would cause a distcleancheck panic.
|
||||
tmpdepfile1=$dir$base.o.d # libtool 1.5
|
||||
tmpdepfile2=$dir.libs/$base.o.d # Likewise.
|
||||
tmpdepfile3=$dir.libs/$base.d # Compaq CCC V6.2-504
|
||||
"$@" -Wc,-MD
|
||||
else
|
||||
tmpdepfile1=$dir$base.d
|
||||
tmpdepfile2=$dir$base.d
|
||||
tmpdepfile3=$dir$base.d
|
||||
"$@" -MD
|
||||
fi
|
||||
|
||||
stat=$?
|
||||
if test $stat -ne 0; then
|
||||
rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
|
||||
exit $stat
|
||||
fi
|
||||
|
||||
for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
|
||||
do
|
||||
test -f "$tmpdepfile" && break
|
||||
done
|
||||
# Same post-processing that is required for AIX mode.
|
||||
aix_post_process_depfile
|
||||
;;
|
||||
|
||||
msvc7)
|
||||
if test "$libtool" = yes; then
|
||||
showIncludes=-Wc,-showIncludes
|
||||
else
|
||||
showIncludes=-showIncludes
|
||||
fi
|
||||
"$@" $showIncludes > "$tmpdepfile"
|
||||
stat=$?
|
||||
grep -v '^Note: including file: ' "$tmpdepfile"
|
||||
if test $stat -ne 0; then
|
||||
rm -f "$tmpdepfile"
|
||||
exit $stat
|
||||
fi
|
||||
rm -f "$depfile"
|
||||
echo "$object : \\" > "$depfile"
|
||||
# The first sed program below extracts the file names and escapes
|
||||
# backslashes for cygpath. The second sed program outputs the file
|
||||
# name when reading, but also accumulates all include files in the
|
||||
# hold buffer in order to output them again at the end. This only
|
||||
# works with sed implementations that can handle large buffers.
|
||||
sed < "$tmpdepfile" -n '
|
||||
/^Note: including file: *\(.*\)/ {
|
||||
s//\1/
|
||||
s/\\/\\\\/g
|
||||
p
|
||||
}' | $cygpath_u | sort -u | sed -n '
|
||||
s/ /\\ /g
|
||||
s/\(.*\)/'"$tab"'\1 \\/p
|
||||
s/.\(.*\) \\/\1:/
|
||||
H
|
||||
$ {
|
||||
s/.*/'"$tab"'/
|
||||
G
|
||||
p
|
||||
}' >> "$depfile"
|
||||
echo >> "$depfile" # make sure the fragment doesn't end with a backslash
|
||||
rm -f "$tmpdepfile"
|
||||
;;
|
||||
|
||||
msvc7msys)
|
||||
# This case exists only to let depend.m4 do its work. It works by
|
||||
# looking at the text of this script. This case will never be run,
|
||||
# since it is checked for above.
|
||||
exit 1
|
||||
;;
|
||||
|
||||
#nosideeffect)
|
||||
# This comment above is used by automake to tell side-effect
|
||||
# dependency tracking mechanisms from slower ones.
|
||||
|
||||
dashmstdout)
|
||||
# Important note: in order to support this mode, a compiler *must*
|
||||
# always write the preprocessed file to stdout, regardless of -o.
|
||||
"$@" || exit $?
|
||||
|
||||
# Remove the call to Libtool.
|
||||
if test "$libtool" = yes; then
|
||||
while test "X$1" != 'X--mode=compile'; do
|
||||
shift
|
||||
done
|
||||
shift
|
||||
fi
|
||||
|
||||
# Remove '-o $object'.
|
||||
IFS=" "
|
||||
for arg
|
||||
do
|
||||
case $arg in
|
||||
-o)
|
||||
shift
|
||||
;;
|
||||
$object)
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
set fnord "$@" "$arg"
|
||||
shift # fnord
|
||||
shift # $arg
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
test -z "$dashmflag" && dashmflag=-M
|
||||
# Require at least two characters before searching for ':'
|
||||
# in the target name. This is to cope with DOS-style filenames:
|
||||
# a dependency such as 'c:/foo/bar' could be seen as target 'c' otherwise.
|
||||
"$@" $dashmflag |
|
||||
sed "s|^[$tab ]*[^:$tab ][^:][^:]*:[$tab ]*|$object: |" > "$tmpdepfile"
|
||||
rm -f "$depfile"
|
||||
cat < "$tmpdepfile" > "$depfile"
|
||||
# Some versions of the HPUX 10.20 sed can't process this sed invocation
|
||||
# correctly. Breaking it into two sed invocations is a workaround.
|
||||
tr ' ' "$nl" < "$tmpdepfile" \
|
||||
| sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' \
|
||||
| sed -e 's/$/ :/' >> "$depfile"
|
||||
rm -f "$tmpdepfile"
|
||||
;;
|
||||
|
||||
dashXmstdout)
|
||||
# This case only exists to satisfy depend.m4. It is never actually
|
||||
# run, as this mode is specially recognized in the preamble.
|
||||
exit 1
|
||||
;;
|
||||
|
||||
makedepend)
|
||||
"$@" || exit $?
|
||||
# Remove any Libtool call
|
||||
if test "$libtool" = yes; then
|
||||
while test "X$1" != 'X--mode=compile'; do
|
||||
shift
|
||||
done
|
||||
shift
|
||||
fi
|
||||
# X makedepend
|
||||
shift
|
||||
cleared=no eat=no
|
||||
for arg
|
||||
do
|
||||
case $cleared in
|
||||
no)
|
||||
set ""; shift
|
||||
cleared=yes ;;
|
||||
esac
|
||||
if test $eat = yes; then
|
||||
eat=no
|
||||
continue
|
||||
fi
|
||||
case "$arg" in
|
||||
-D*|-I*)
|
||||
set fnord "$@" "$arg"; shift ;;
|
||||
# Strip any option that makedepend may not understand. Remove
|
||||
# the object too, otherwise makedepend will parse it as a source file.
|
||||
-arch)
|
||||
eat=yes ;;
|
||||
-*|$object)
|
||||
;;
|
||||
*)
|
||||
set fnord "$@" "$arg"; shift ;;
|
||||
esac
|
||||
done
|
||||
obj_suffix=`echo "$object" | sed 's/^.*\././'`
|
||||
touch "$tmpdepfile"
|
||||
${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@"
|
||||
rm -f "$depfile"
|
||||
# makedepend may prepend the VPATH from the source file name to the object.
|
||||
# No need to regex-escape $object, excess matching of '.' is harmless.
|
||||
sed "s|^.*\($object *:\)|\1|" "$tmpdepfile" > "$depfile"
|
||||
# Some versions of the HPUX 10.20 sed can't process the last invocation
|
||||
# correctly. Breaking it into two sed invocations is a workaround.
|
||||
sed '1,2d' "$tmpdepfile" \
|
||||
| tr ' ' "$nl" \
|
||||
| sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' \
|
||||
| sed -e 's/$/ :/' >> "$depfile"
|
||||
rm -f "$tmpdepfile" "$tmpdepfile".bak
|
||||
;;
|
||||
|
||||
cpp)
|
||||
# Important note: in order to support this mode, a compiler *must*
|
||||
# always write the preprocessed file to stdout.
|
||||
"$@" || exit $?
|
||||
|
||||
# Remove the call to Libtool.
|
||||
if test "$libtool" = yes; then
|
||||
while test "X$1" != 'X--mode=compile'; do
|
||||
shift
|
||||
done
|
||||
shift
|
||||
fi
|
||||
|
||||
# Remove '-o $object'.
|
||||
IFS=" "
|
||||
for arg
|
||||
do
|
||||
case $arg in
|
||||
-o)
|
||||
shift
|
||||
;;
|
||||
$object)
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
set fnord "$@" "$arg"
|
||||
shift # fnord
|
||||
shift # $arg
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
"$@" -E \
|
||||
| sed -n -e '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \
|
||||
-e '/^#line [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \
|
||||
| sed '$ s: \\$::' > "$tmpdepfile"
|
||||
rm -f "$depfile"
|
||||
echo "$object : \\" > "$depfile"
|
||||
cat < "$tmpdepfile" >> "$depfile"
|
||||
sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile"
|
||||
rm -f "$tmpdepfile"
|
||||
;;
|
||||
|
||||
msvisualcpp)
|
||||
# Important note: in order to support this mode, a compiler *must*
|
||||
# always write the preprocessed file to stdout.
|
||||
"$@" || exit $?
|
||||
|
||||
# Remove the call to Libtool.
|
||||
if test "$libtool" = yes; then
|
||||
while test "X$1" != 'X--mode=compile'; do
|
||||
shift
|
||||
done
|
||||
shift
|
||||
fi
|
||||
|
||||
IFS=" "
|
||||
for arg
|
||||
do
|
||||
case "$arg" in
|
||||
-o)
|
||||
shift
|
||||
;;
|
||||
$object)
|
||||
shift
|
||||
;;
|
||||
"-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI")
|
||||
set fnord "$@"
|
||||
shift
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
set fnord "$@" "$arg"
|
||||
shift
|
||||
shift
|
||||
;;
|
||||
esac
|
||||
done
|
||||
"$@" -E 2>/dev/null |
|
||||
sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::\1:p' | $cygpath_u | sort -u > "$tmpdepfile"
|
||||
rm -f "$depfile"
|
||||
echo "$object : \\" > "$depfile"
|
||||
sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::'"$tab"'\1 \\:p' >> "$depfile"
|
||||
echo "$tab" >> "$depfile"
|
||||
sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::\1\::p' >> "$depfile"
|
||||
rm -f "$tmpdepfile"
|
||||
;;
|
||||
|
||||
msvcmsys)
|
||||
# This case exists only to let depend.m4 do its work. It works by
|
||||
# looking at the text of this script. This case will never be run,
|
||||
# since it is checked for above.
|
||||
exit 1
|
||||
;;
|
||||
|
||||
none)
|
||||
exec "$@"
|
||||
;;
|
||||
|
||||
*)
|
||||
echo "Unknown depmode $depmode" 1>&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
exit 0
|
||||
|
||||
# Local Variables:
|
||||
# mode: shell-script
|
||||
# sh-indentation: 2
|
||||
# eval: (add-hook 'write-file-hooks 'time-stamp)
|
||||
# time-stamp-start: "scriptversion="
|
||||
# time-stamp-format: "%:y-%02m-%02d.%02H"
|
||||
# time-stamp-time-zone: "UTC"
|
||||
# time-stamp-end: "; # UTC"
|
||||
# End:
|
|
@ -1,5 +0,0 @@
|
|||
[{000214A0-0000-0000-C000-000000000046}]
|
||||
Prop3=19,11
|
||||
[InternetShortcut]
|
||||
IDList=
|
||||
URL=https://github.com/sifive/freedom-metal-docs
|
|
@ -44,22 +44,7 @@ _start:
|
|||
la gp, __global_pointer$
|
||||
.option pop
|
||||
|
||||
/* The METAL is designed for a bare-metal environment and therefor is expected
|
||||
* to define its own stack pointer. We also align the stack pointer here
|
||||
* because the only RISC-V ABI that's currently defined mandates 16-byte
|
||||
* stack alignment. */
|
||||
la sp, _sp
|
||||
|
||||
/* Increment by hartid number of stack sizes */
|
||||
li t0, 0
|
||||
la t1, __stack_size
|
||||
1:
|
||||
beq t0, a0, 1f
|
||||
add sp, sp, t1
|
||||
addi t0, t0, 1
|
||||
j 1b
|
||||
1:
|
||||
andi sp, sp, -16
|
||||
/* Stack pointer is expected to be initialized before _start */
|
||||
|
||||
/* If we're not hart 0, skip the initialization work */
|
||||
la t0, __metal_boot_hart
|
||||
|
@ -123,6 +108,36 @@ _start:
|
|||
complete */
|
||||
fence.i
|
||||
|
||||
2:
|
||||
|
||||
/* Copy the LIM section */
|
||||
la t0, metal_segment_lim_source_start
|
||||
la t1, metal_segment_lim_target_start
|
||||
la t2, metal_segment_lim_target_end
|
||||
|
||||
beq t0, t1, 2f
|
||||
bge t1, t2, 2f
|
||||
|
||||
1:
|
||||
#if __riscv_xlen == 32
|
||||
lw a0, 0(t0)
|
||||
addi t0, t0, 4
|
||||
sw a0, 0(t1)
|
||||
addi t1, t1, 4
|
||||
blt t1, t2, 1b
|
||||
#else
|
||||
ld a0, 0(t0)
|
||||
addi t0, t0, 8
|
||||
sd a0, 0(t1)
|
||||
addi t1, t1, 8
|
||||
blt t1, t2, 1b
|
||||
#endif
|
||||
2:
|
||||
|
||||
/* Fence all subsequent instruction fetches until after the LIM writes
|
||||
complete */
|
||||
fence.i
|
||||
|
||||
/* Zero the BSS segment. */
|
||||
la t1, metal_segment_bss_target_start
|
||||
la t2, metal_segment_bss_target_end
|
||||
|
@ -141,6 +156,10 @@ _start:
|
|||
#endif
|
||||
2:
|
||||
|
||||
/* Set TLS pointer */
|
||||
.weak __tls_base
|
||||
la tp, __tls_base
|
||||
|
||||
/* At this point we're in an environment that can execute C code. The first
|
||||
* thing to do is to make the callback to the parent environment if it's been
|
||||
* requested to do so. */
|
||||
|
@ -153,14 +172,41 @@ _start:
|
|||
call atexit
|
||||
call __libc_init_array
|
||||
|
||||
/* Register metal_fini_run as a destructor and call metal_init_run to
|
||||
* run and setup Metal constructors */
|
||||
la a0, metal_fini_run
|
||||
call atexit
|
||||
call metal_init_run
|
||||
|
||||
_skip_init:
|
||||
|
||||
/* Synchronize harts so that secondary harts wait until hart 0 finishes
|
||||
initializing */
|
||||
call __metal_synchronize_harts
|
||||
|
||||
/* Check RISC-V isa and enable FS bits if Floating Point architecture. */
|
||||
/* Disable and clear all interrupt sources */
|
||||
li a3, -1
|
||||
csrc mie, a3
|
||||
csrc mip, a3
|
||||
|
||||
/* The delegation CSRs exist if user mode interrupts (N extension) or
|
||||
* supervisor mode (S extension) are supported */
|
||||
csrr a5, misa
|
||||
lui a4, 0x42
|
||||
and a4, a4, a5
|
||||
beqz a4, 1f
|
||||
csrc mideleg, a3
|
||||
csrc medeleg, a3
|
||||
1:
|
||||
|
||||
/* The satp CSR exists if supervisor mode (S extension) is supported */
|
||||
lui a4, 0x40
|
||||
and a4, a4, a5
|
||||
beqz a4, 1f
|
||||
csrc satp, a3
|
||||
1:
|
||||
|
||||
/* Check RISC-V isa and enable FS bits if Floating Point architecture. */
|
||||
li a4, 0x10028
|
||||
and a5, a5, a4
|
||||
beqz a5, 1f
|
||||
|
@ -171,6 +217,16 @@ _skip_init:
|
|||
csrwi fcsr, 0
|
||||
1:
|
||||
|
||||
/* Check for vector extension support and enable it if found */
|
||||
csrr a5, misa
|
||||
li a4, 0x200000
|
||||
and a5, a5, a4
|
||||
beqz a5, 1f
|
||||
csrr a5, mstatus
|
||||
ori a5, a5, 0x200
|
||||
csrw mstatus, a5
|
||||
1:
|
||||
|
||||
/* This is a C runtime, so main() is defined to have some arguments. Since
|
||||
* there's nothing sane the METAL can pass we don't bother with that but
|
||||
* instead just setup as close to a NOP as we can. */
|
||||
|
|
|
@ -1,9 +1,7 @@
|
|||
#include <errno.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
int
|
||||
nanosleep(const struct timespec *rqtp, struct timespec *rmtp)
|
||||
{
|
||||
int nanosleep(const struct timespec *rqtp, struct timespec *rmtp) {
|
||||
errno = ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
|
|
|
@ -1,59 +0,0 @@
|
|||
/* Copyright 2019 SiFive, Inc */
|
||||
/* SPDX-License-Identifier: Apache-2.0 */
|
||||
|
||||
#include <metal/machine.h>
|
||||
#include <metal/machine/platform.h>
|
||||
#include <metal/io.h>
|
||||
#include <metal/cpu.h>
|
||||
|
||||
#define METAL_REG(base, offset) (((unsigned long)(base) + (offset)))
|
||||
#define METAL_REGW(base, offset) (__METAL_ACCESS_ONCE((__metal_io_u32 *)METAL_REG((base), (offset))))
|
||||
#define METAL_MSIP(base, hart) (METAL_REGW((base),4*(hart)))
|
||||
|
||||
/*
|
||||
* _synchronize_harts() is called by crt0.S to cause harts > 0 to wait for
|
||||
* hart 0 to finish copying the datat section, zeroing the BSS, and running
|
||||
* the libc contstructors.
|
||||
*/
|
||||
void _synchronize_harts() {
|
||||
#if __METAL_DT_MAX_HARTS > 1
|
||||
|
||||
int hart = metal_cpu_get_current_hartid();
|
||||
uintptr_t msip_base = 0;
|
||||
|
||||
/* Get the base address of the MSIP registers */
|
||||
#ifdef __METAL_DT_RISCV_CLINT0_HANDLE
|
||||
msip_base = __metal_driver_sifive_clint0_control_base(__METAL_DT_RISCV_CLINT0_HANDLE);
|
||||
msip_base += METAL_RISCV_CLINT0_MSIP_BASE;
|
||||
#elif __METAL_DT_RISCV_CLIC0_HANDLE
|
||||
msip_base = __metal_driver_sifive_clic0_control_base(__METAL_DT_RISCV_CLIC0_HANDLE);
|
||||
msip_base += METAL_RISCV_CLIC0_MSIP_BASE;
|
||||
#else
|
||||
#warning No handle for CLINT or CLIC found, harts may be unsynchronized after init!
|
||||
#endif
|
||||
|
||||
/* Disable machine interrupts as a precaution */
|
||||
__asm__ volatile("csrc mstatus, %0" :: "r" (METAL_MSTATUS_MIE));
|
||||
|
||||
if (hart == 0) {
|
||||
/* Hart 0 waits for all harts to set their MSIP bit */
|
||||
for (int i = 1 ; i < __METAL_DT_MAX_HARTS; i++) {
|
||||
while (METAL_MSIP(msip_base, i) == 0) ;
|
||||
}
|
||||
|
||||
/* Hart 0 clears everyone's MSIP bit */
|
||||
for (int i = 1 ; i < __METAL_DT_MAX_HARTS; i++) {
|
||||
METAL_MSIP(msip_base, i) = 0;
|
||||
}
|
||||
} else {
|
||||
/* Other harts set their MSIP bit to indicate they're ready */
|
||||
METAL_MSIP(msip_base, hart) = 1;
|
||||
__asm__ volatile ("fence w,rw");
|
||||
|
||||
/* Wait for hart 0 to clear the MSIP bit */
|
||||
while (METAL_MSIP(msip_base, hart) == 1) ;
|
||||
}
|
||||
|
||||
#endif /* __METAL_DT_MAX_HARTS > 1 */
|
||||
}
|
||||
|
|
@ -1,8 +1,6 @@
|
|||
#include <errno.h>
|
||||
|
||||
int
|
||||
_access(const char *file, int mode)
|
||||
{
|
||||
int _access(const char *file, int mode) {
|
||||
errno = ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
#include <errno.h>
|
||||
|
||||
int
|
||||
_chdir(const char *path)
|
||||
{
|
||||
int _chdir(const char *path) {
|
||||
errno = ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
|
|
|
@ -1,9 +1,7 @@
|
|||
#include <errno.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
int
|
||||
_chmod(const char *path, mode_t mode)
|
||||
{
|
||||
int _chmod(const char *path, mode_t mode) {
|
||||
errno = ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue