Commit d7b26872 authored by Henrique Silva's avatar Henrique Silva

Merge branch 'devel' into master

parents 890b3a7a 8c4fcf39
<?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="com.crt.advproject.config.exe.debug.1670967295">
<storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="com.crt.advproject.config.exe.debug.1670967295" moduleId="org.eclipse.cdt.core.settings" name="Debug">
<externalSettings/>
<extensions>
<extension id="org.eclipse.cdt.core.GmakeErrorParser" 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"/>
<extension id="org.eclipse.cdt.core.GASErrorParser" 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.ELF" point="org.eclipse.cdt.core.BinaryParser"/>
<extension id="org.eclipse.cdt.core.GNU_ELF" point="org.eclipse.cdt.core.BinaryParser"/>
</extensions>
</storageModule>
<storageModule moduleId="cdtBuildSystem" version="4.0.0">
<configuration artifactExtension="axf" artifactName="${ProjName}" buildArtefactType="org.eclipse.cdt.build.core.buildArtefactType.exe" buildProperties="org.eclipse.cdt.build.core.buildArtefactType=org.eclipse.cdt.build.core.buildArtefactType.exe" cleanCommand="rm -rf" description="Debug build" errorParsers="org.eclipse.cdt.core.CWDLocator;org.eclipse.cdt.core.GmakeErrorParser;org.eclipse.cdt.core.GCCErrorParser;org.eclipse.cdt.core.GLDErrorParser;org.eclipse.cdt.core.GASErrorParser" id="com.crt.advproject.config.exe.debug.1670967295" name="Debug" parent="com.crt.advproject.config.exe.debug" postannouncebuildStep="Performing post-build steps" postbuildStep="arm-none-eabi-size &quot;${BuildArtifactFileName}&quot;; # arm-none-eabi-objcopy -v -O binary &quot;${BuildArtifactFileName}&quot; &quot;${BuildArtifactFileBaseName}.bin&quot; ; # checksum -p ${TargetChip} -d &quot;${BuildArtifactFileBaseName}.bin&quot;; ">
<folderInfo id="com.crt.advproject.config.exe.debug.1670967295." name="/" resourcePath="">
<toolChain id="com.crt.advproject.toolchain.exe.debug.894957502" name="NXP MCU Tools" superClass="com.crt.advproject.toolchain.exe.debug">
<targetPlatform binaryParser="org.eclipse.cdt.core.ELF;org.eclipse.cdt.core.GNU_ELF" id="com.crt.advproject.platform.exe.debug.2138056934" name="ARM-based MCU (Debug)" superClass="com.crt.advproject.platform.exe.debug"/>
<builder arguments="-C ~/rep/afcipm/" autoBuildTarget="all" buildPath="${workspace_loc:/afcipm}/out" cleanBuildTarget="clean" command="make" enableAutoBuild="false" enableCleanBuild="true" enabledIncrementalBuild="true" id="com.crt.advproject.builder.exe.debug.1486561543" incrementalBuildTarget="all" keepEnvironmentInBuildfile="false" managedBuildOn="false" name="Gnu Make Builder" parallelBuildOn="false" superClass="com.crt.advproject.builder.exe.debug"/>
<tool id="com.crt.advproject.cpp.exe.debug.1328011625" name="MCU C++ Compiler" superClass="com.crt.advproject.cpp.exe.debug"/>
<tool id="com.crt.advproject.gcc.exe.debug.1945863734" name="MCU C Compiler" superClass="com.crt.advproject.gcc.exe.debug">
<option id="com.crt.advproject.gcc.arch.1115112193" name="Architecture" superClass="com.crt.advproject.gcc.arch" value="com.crt.advproject.gcc.target.cm3" valueType="enumerated"/>
<option id="com.crt.advproject.gcc.thumb.1343601503" name="Thumb mode" superClass="com.crt.advproject.gcc.thumb" value="true" valueType="boolean"/>
<option id="gnu.c.compiler.option.preprocessor.def.symbols.1330755002" name="Defined symbols (-D)" superClass="gnu.c.compiler.option.preprocessor.def.symbols" valueType="definedSymbols">
<listOptionValue builtIn="false" value="DEBUG"/>
<listOptionValue builtIn="false" value="__CODE_RED"/>
<listOptionValue builtIn="false" value="CORE_M3"/>
<listOptionValue builtIn="false" value="__USE_LPCOPEN"/>
<listOptionValue builtIn="false" value="NO_BOARD_LIB"/>
<listOptionValue builtIn="false" value="__LPC17XX__"/>
<listOptionValue builtIn="false" value="__NEWLIB__"/>
</option>
<option id="gnu.c.compiler.option.misc.other.1311155275" name="Other flags" superClass="gnu.c.compiler.option.misc.other" value="-c -fmessage-length=0 -fno-builtin -ffunction-sections -fdata-sections" valueType="string"/>
<option id="com.crt.advproject.gcc.hdrlib.241911327" name="Library headers" superClass="com.crt.advproject.gcc.hdrlib" value="com.crt.advproject.gcc.hdrlib.newlib" valueType="enumerated"/>
<option id="com.crt.advproject.gcc.specs.1065491347" name="Specs" superClass="com.crt.advproject.gcc.specs" value="com.crt.advproject.gcc.specs.newlib" valueType="enumerated"/>
<option id="gnu.c.compiler.option.include.paths.631807154" name="Include paths (-I)" superClass="gnu.c.compiler.option.include.paths" valueType="includePath">
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/lpc_chip_175x_6x/inc}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/inc}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/FreeRTOS/include}&quot;"/>
</option>
<inputType id="com.crt.advproject.compiler.input.1115792193" superClass="com.crt.advproject.compiler.input"/>
</tool>
<tool id="com.crt.advproject.gas.exe.debug.230675243" name="MCU Assembler" superClass="com.crt.advproject.gas.exe.debug">
<option id="com.crt.advproject.gas.arch.2074619661" name="Architecture" superClass="com.crt.advproject.gas.arch" value="com.crt.advproject.gas.target.cm3" valueType="enumerated"/>
<option id="com.crt.advproject.gas.thumb.892901470" name="Thumb mode" superClass="com.crt.advproject.gas.thumb" value="true" valueType="boolean"/>
<option id="gnu.both.asm.option.flags.crt.1164410857" name="Assembler flags" superClass="gnu.both.asm.option.flags.crt" value="-c -x assembler-with-cpp -DDEBUG -D__CODE_RED -DCORE_M3 -D__USE_LPCOPEN -DNO_BOARD_LIB -D__LPC17XX__ -D__NEWLIB__" valueType="string"/>
<option id="com.crt.advproject.gas.hdrlib.1034120581" name="Library headers" superClass="com.crt.advproject.gas.hdrlib" value="com.crt.advproject.gas.hdrlib.newlib" valueType="enumerated"/>
<option id="com.crt.advproject.gas.specs.1609652612" name="Specs" superClass="com.crt.advproject.gas.specs" value="com.crt.advproject.gas.specs.newlib" valueType="enumerated"/>
<option id="gnu.both.asm.option.include.paths.1729761761" name="Include paths (-I)" superClass="gnu.both.asm.option.include.paths" valueType="includePath">
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/lpc_chip_175x_6x/inc}&quot;"/>
</option>
<inputType id="cdt.managedbuild.tool.gnu.assembler.input.1592699680" superClass="cdt.managedbuild.tool.gnu.assembler.input"/>
<inputType id="com.crt.advproject.assembler.input.1553637287" name="Additional Assembly Source Files" superClass="com.crt.advproject.assembler.input"/>
</tool>
<tool id="com.crt.advproject.link.cpp.exe.debug.1484449358" name="MCU C++ Linker" superClass="com.crt.advproject.link.cpp.exe.debug"/>
<tool id="com.crt.advproject.link.exe.debug.862713800" name="MCU Linker" superClass="com.crt.advproject.link.exe.debug">
<option id="com.crt.advproject.link.gcc.multicore.master.userobjs.1004380254" name="Slave Objects (not visible)" superClass="com.crt.advproject.link.gcc.multicore.master.userobjs" valueType="userObjs"/>
<option id="com.crt.advproject.link.arch.1889725838" name="Architecture" superClass="com.crt.advproject.link.arch" value="com.crt.advproject.link.target.cm3" valueType="enumerated"/>
<option id="com.crt.advproject.link.thumb.974532348" name="Thumb mode" superClass="com.crt.advproject.link.thumb" value="true" valueType="boolean"/>
<option id="com.crt.advproject.link.script.396728350" name="Linker script" superClass="com.crt.advproject.link.script" value="&quot;afcipm_Debug.ld&quot;" valueType="string"/>
<option id="com.crt.advproject.link.manage.471654280" name="Manage linker script" superClass="com.crt.advproject.link.manage" value="true" valueType="boolean"/>
<option id="gnu.c.link.option.nostdlibs.2102086593" name="No startup or default libs (-nostdlib)" superClass="gnu.c.link.option.nostdlibs" value="true" valueType="boolean"/>
<option id="gnu.c.link.option.other.795360448" name="Other options (-Xlinker [option])" superClass="gnu.c.link.option.other" valueType="stringList">
<listOptionValue builtIn="false" value="-Map=&quot;${BuildArtifactFileBaseName}.map&quot;"/>
<listOptionValue builtIn="false" value="--gc-sections"/>
</option>
<option id="com.crt.advproject.link.gcc.hdrlib.340870349" name="Library" superClass="com.crt.advproject.link.gcc.hdrlib" value="com.crt.advproject.gcc.link.hdrlib.newlib.nohost" valueType="enumerated"/>
<option id="gnu.c.link.option.libs.337518226" name="Libraries (-l)" superClass="gnu.c.link.option.libs" valueType="libs">
<listOptionValue builtIn="false" value="lpc_chip_175x_6x"/>
</option>
<option id="gnu.c.link.option.paths.959245234" name="Library search path (-L)" superClass="gnu.c.link.option.paths" valueType="libPaths">
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/lpc_chip_175x_6x/Debug}&quot;"/>
</option>
<option id="com.crt.advproject.link.crpenable.562918545" name="Enable Code Read Protect" superClass="com.crt.advproject.link.crpenable"/>
<option id="com.crt.advproject.link.gcc.multicore.slave.699359122" name="Multicore configuration" superClass="com.crt.advproject.link.gcc.multicore.slave"/>
<inputType id="cdt.managedbuild.tool.gnu.c.linker.input.1946699854" superClass="cdt.managedbuild.tool.gnu.c.linker.input">
<additionalInput kind="additionalinputdependency" paths="$(USER_OBJS)"/>
<additionalInput kind="additionalinput" paths="$(LIBS)"/>
</inputType>
</tool>
</toolChain>
</folderInfo>
<sourceEntries>
<entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="FreeRTOS"/>
<entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="src"/>
</sourceEntries>
</configuration>
</storageModule>
<storageModule moduleId="org.eclipse.cdt.core.externalSettings"/>
</cconfiguration>
<cconfiguration id="com.crt.advproject.config.exe.release.1211394630">
<storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="com.crt.advproject.config.exe.release.1211394630" moduleId="org.eclipse.cdt.core.settings" name="Release">
<externalSettings/>
<extensions>
<extension id="org.eclipse.cdt.core.GmakeErrorParser" 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"/>
<extension id="org.eclipse.cdt.core.GASErrorParser" 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.ELF" point="org.eclipse.cdt.core.BinaryParser"/>
<extension id="org.eclipse.cdt.core.GNU_ELF" point="org.eclipse.cdt.core.BinaryParser"/>
</extensions>
</storageModule>
<storageModule moduleId="cdtBuildSystem" version="4.0.0">
<configuration artifactExtension="axf" artifactName="${ProjName}" buildArtefactType="org.eclipse.cdt.build.core.buildArtefactType.exe" buildProperties="org.eclipse.cdt.build.core.buildArtefactType=org.eclipse.cdt.build.core.buildArtefactType.exe" cleanCommand="rm -rf" description="Release build" errorParsers="org.eclipse.cdt.core.CWDLocator;org.eclipse.cdt.core.GmakeErrorParser;org.eclipse.cdt.core.GCCErrorParser;org.eclipse.cdt.core.GLDErrorParser;org.eclipse.cdt.core.GASErrorParser" id="com.crt.advproject.config.exe.release.1211394630" name="Release" parent="com.crt.advproject.config.exe.release" postannouncebuildStep="Performing post-build steps" postbuildStep="arm-none-eabi-size &quot;${BuildArtifactFileName}&quot;; # arm-none-eabi-objcopy -v -O binary &quot;${BuildArtifactFileName}&quot; &quot;${BuildArtifactFileBaseName}.bin&quot; ; # checksum -p ${TargetChip} -d &quot;${BuildArtifactFileBaseName}.bin&quot;; ">
<folderInfo id="com.crt.advproject.config.exe.release.1211394630." name="/" resourcePath="">
<toolChain id="com.crt.advproject.toolchain.exe.release.301157497" name="NXP MCU Tools" superClass="com.crt.advproject.toolchain.exe.release">
<targetPlatform binaryParser="org.eclipse.cdt.core.ELF;org.eclipse.cdt.core.GNU_ELF" id="com.crt.advproject.platform.exe.release.908962772" name="ARM-based MCU (Release)" superClass="com.crt.advproject.platform.exe.release"/>
<builder buildPath="${workspace_loc:/afcipm}/Release" id="com.crt.advproject.builder.exe.release.715075419" keepEnvironmentInBuildfile="false" managedBuildOn="true" name="Gnu Make Builder" superClass="com.crt.advproject.builder.exe.release"/>
<tool id="com.crt.advproject.cpp.exe.release.1411065156" name="MCU C++ Compiler" superClass="com.crt.advproject.cpp.exe.release"/>
<tool id="com.crt.advproject.gcc.exe.release.1568753254" name="MCU C Compiler" superClass="com.crt.advproject.gcc.exe.release">
<option id="com.crt.advproject.gcc.arch.174168494" name="Architecture" superClass="com.crt.advproject.gcc.arch" value="com.crt.advproject.gcc.target.cm3" valueType="enumerated"/>
<option id="com.crt.advproject.gcc.thumb.1529061698" name="Thumb mode" superClass="com.crt.advproject.gcc.thumb" value="true" valueType="boolean"/>
<option id="gnu.c.compiler.option.preprocessor.def.symbols.533773256" name="Defined symbols (-D)" superClass="gnu.c.compiler.option.preprocessor.def.symbols" valueType="definedSymbols">
<listOptionValue builtIn="false" value="NDEBUG"/>
<listOptionValue builtIn="false" value="__CODE_RED"/>
<listOptionValue builtIn="false" value="CORE_M3"/>
<listOptionValue builtIn="false" value="__USE_LPCOPEN"/>
<listOptionValue builtIn="false" value="NO_BOARD_LIB"/>
<listOptionValue builtIn="false" value="__LPC17XX__"/>
<listOptionValue builtIn="false" value="__NEWLIB__"/>
</option>
<option id="gnu.c.compiler.option.misc.other.573524572" name="Other flags" superClass="gnu.c.compiler.option.misc.other" value="-c -fmessage-length=0 -fno-builtin -ffunction-sections -fdata-sections" valueType="string"/>
<option id="com.crt.advproject.gcc.hdrlib.1631642560" name="Library headers" superClass="com.crt.advproject.gcc.hdrlib" value="com.crt.advproject.gcc.hdrlib.newlib" valueType="enumerated"/>
<option id="com.crt.advproject.gcc.specs.1784800843" name="Specs" superClass="com.crt.advproject.gcc.specs" value="com.crt.advproject.gcc.specs.newlib" valueType="enumerated"/>
<option id="gnu.c.compiler.option.include.paths.580764710" name="Include paths (-I)" superClass="gnu.c.compiler.option.include.paths" valueType="includePath">
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/lpc_chip_175x_6x/inc}&quot;"/>
</option>
<inputType id="com.crt.advproject.compiler.input.841762798" superClass="com.crt.advproject.compiler.input"/>
</tool>
<tool id="com.crt.advproject.gas.exe.release.663323907" name="MCU Assembler" superClass="com.crt.advproject.gas.exe.release">
<option id="com.crt.advproject.gas.arch.1217199942" name="Architecture" superClass="com.crt.advproject.gas.arch" value="com.crt.advproject.gas.target.cm3" valueType="enumerated"/>
<option id="com.crt.advproject.gas.thumb.1394142528" name="Thumb mode" superClass="com.crt.advproject.gas.thumb" value="true" valueType="boolean"/>
<option id="gnu.both.asm.option.flags.crt.1590819336" name="Assembler flags" superClass="gnu.both.asm.option.flags.crt" value="-c -x assembler-with-cpp -DNDEBUG -D__CODE_RED -DCORE_M3 -D__USE_LPCOPEN -DNO_BOARD_LIB -D__LPC17XX__ -D__NEWLIB__" valueType="string"/>
<option id="com.crt.advproject.gas.hdrlib.820440520" name="Library headers" superClass="com.crt.advproject.gas.hdrlib" value="com.crt.advproject.gas.hdrlib.newlib" valueType="enumerated"/>
<option id="com.crt.advproject.gas.specs.324029214" name="Specs" superClass="com.crt.advproject.gas.specs" value="com.crt.advproject.gas.specs.newlib" valueType="enumerated"/>
<option id="gnu.both.asm.option.include.paths.1948657572" name="Include paths (-I)" superClass="gnu.both.asm.option.include.paths" valueType="includePath">
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/lpc_chip_175x_6x/inc}&quot;"/>
</option>
<inputType id="cdt.managedbuild.tool.gnu.assembler.input.1541807420" superClass="cdt.managedbuild.tool.gnu.assembler.input"/>
<inputType id="com.crt.advproject.assembler.input.1886129146" name="Additional Assembly Source Files" superClass="com.crt.advproject.assembler.input"/>
</tool>
<tool id="com.crt.advproject.link.cpp.exe.release.512232272" name="MCU C++ Linker" superClass="com.crt.advproject.link.cpp.exe.release"/>
<tool id="com.crt.advproject.link.exe.release.2030692412" name="MCU Linker" superClass="com.crt.advproject.link.exe.release">
<option id="com.crt.advproject.link.gcc.multicore.master.userobjs.1415899991" name="Slave Objects (not visible)" superClass="com.crt.advproject.link.gcc.multicore.master.userobjs" valueType="userObjs"/>
<option id="com.crt.advproject.link.arch.580808098" name="Architecture" superClass="com.crt.advproject.link.arch" value="com.crt.advproject.link.target.cm3" valueType="enumerated"/>
<option id="com.crt.advproject.link.thumb.1195203099" name="Thumb mode" superClass="com.crt.advproject.link.thumb" value="true" valueType="boolean"/>
<option id="com.crt.advproject.link.script.2025578867" name="Linker script" superClass="com.crt.advproject.link.script" value="&quot;afcipm_Release.ld&quot;" valueType="string"/>
<option id="com.crt.advproject.link.manage.621611650" name="Manage linker script" superClass="com.crt.advproject.link.manage" value="true" valueType="boolean"/>
<option id="gnu.c.link.option.nostdlibs.129051733" name="No startup or default libs (-nostdlib)" superClass="gnu.c.link.option.nostdlibs" value="true" valueType="boolean"/>
<option id="gnu.c.link.option.other.237325496" name="Other options (-Xlinker [option])" superClass="gnu.c.link.option.other" valueType="stringList">
<listOptionValue builtIn="false" value="-Map=&quot;${BuildArtifactFileBaseName}.map&quot;"/>
<listOptionValue builtIn="false" value="--gc-sections"/>
</option>
<option id="com.crt.advproject.link.gcc.hdrlib.859045042" name="Library" superClass="com.crt.advproject.link.gcc.hdrlib" value="com.crt.advproject.gcc.link.hdrlib.newlib.nohost" valueType="enumerated"/>
<option id="gnu.c.link.option.libs.1925313136" name="Libraries (-l)" superClass="gnu.c.link.option.libs" valueType="libs">
<listOptionValue builtIn="false" value="lpc_chip_175x_6x"/>
</option>
<option id="gnu.c.link.option.paths.31611246" name="Library search path (-L)" superClass="gnu.c.link.option.paths" valueType="libPaths">
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/lpc_chip_175x_6x/Release}&quot;"/>
</option>
<option id="com.crt.advproject.link.crpenable.1945908093" name="Enable Code Read Protect" superClass="com.crt.advproject.link.crpenable"/>
<option id="com.crt.advproject.link.gcc.multicore.slave.1404690422" name="Multicore configuration" superClass="com.crt.advproject.link.gcc.multicore.slave"/>
<inputType id="cdt.managedbuild.tool.gnu.c.linker.input.1255970445" superClass="cdt.managedbuild.tool.gnu.c.linker.input">
<additionalInput kind="additionalinputdependency" paths="$(USER_OBJS)"/>
<additionalInput kind="additionalinput" paths="$(LIBS)"/>
</inputType>
</tool>
</toolChain>
</folderInfo>
<sourceEntries>
<entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="src"/>
</sourceEntries>
</configuration>
</storageModule>
<storageModule moduleId="org.eclipse.cdt.core.externalSettings"/>
</cconfiguration>
<cconfiguration id="cdt.managedbuild.toolchain.gnu.base.737223558">
<storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="cdt.managedbuild.toolchain.gnu.base.737223558" moduleId="org.eclipse.cdt.core.settings" name="Default">
<externalSettings/>
<extensions>
<extension id="org.eclipse.cdt.core.GmakeErrorParser" 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"/>
<extension id="org.eclipse.cdt.core.GASErrorParser" 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.ELF" point="org.eclipse.cdt.core.BinaryParser"/>
</extensions>
</storageModule>
<storageModule moduleId="cdtBuildSystem" version="4.0.0">
<configuration buildProperties="" id="cdt.managedbuild.toolchain.gnu.base.737223558" name="Default" parent="org.eclipse.cdt.build.core.emptycfg">
<folderInfo id="cdt.managedbuild.toolchain.gnu.base.737223558.752222238" name="/" resourcePath="">
<toolChain id="cdt.managedbuild.toolchain.gnu.base.196575119" name="Linux GCC" superClass="cdt.managedbuild.toolchain.gnu.base">
<targetPlatform archList="all" binaryParser="org.eclipse.cdt.core.ELF" id="cdt.managedbuild.target.gnu.platform.base.2028143790" name="Debug Platform" osList="linux,hpux,aix,qnx" superClass="cdt.managedbuild.target.gnu.platform.base"/>
<builder id="cdt.managedbuild.target.gnu.builder.base.149545657" managedBuildOn="false" name="Gnu Make Builder.Default" superClass="cdt.managedbuild.target.gnu.builder.base"/>
<tool id="cdt.managedbuild.tool.gnu.archiver.base.667164995" name="GCC Archiver" superClass="cdt.managedbuild.tool.gnu.archiver.base"/>
<tool id="cdt.managedbuild.tool.gnu.cpp.compiler.base.1613043905" name="GCC C++ Compiler" superClass="cdt.managedbuild.tool.gnu.cpp.compiler.base">
<inputType id="cdt.managedbuild.tool.gnu.cpp.compiler.input.2045698561" superClass="cdt.managedbuild.tool.gnu.cpp.compiler.input"/>
</tool>
<tool id="cdt.managedbuild.tool.gnu.c.compiler.base.1732767375" name="GCC C Compiler" superClass="cdt.managedbuild.tool.gnu.c.compiler.base">
<inputType id="cdt.managedbuild.tool.gnu.c.compiler.input.962992190" superClass="cdt.managedbuild.tool.gnu.c.compiler.input"/>
</tool>
<tool id="cdt.managedbuild.tool.gnu.c.linker.base.788645257" name="GCC C Linker" superClass="cdt.managedbuild.tool.gnu.c.linker.base">
<inputType id="cdt.managedbuild.tool.gnu.c.linker.input.2116243449" 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.cpp.linker.base.1556322811" name="GCC C++ Linker" superClass="cdt.managedbuild.tool.gnu.cpp.linker.base">
<inputType id="cdt.managedbuild.tool.gnu.cpp.linker.input.917395708" superClass="cdt.managedbuild.tool.gnu.cpp.linker.input">
<additionalInput kind="additionalinputdependency" paths="$(USER_OBJS)"/>
<additionalInput kind="additionalinput" paths="$(LIBS)"/>
</inputType>
</tool>
<tool id="cdt.managedbuild.tool.gnu.assembler.base.1752133391" name="GCC Assembler" superClass="cdt.managedbuild.tool.gnu.assembler.base">
<inputType id="cdt.managedbuild.tool.gnu.assembler.input.1136844114" superClass="cdt.managedbuild.tool.gnu.assembler.input"/>
</tool>
</toolChain>
</folderInfo>
</configuration>
</storageModule>
<storageModule moduleId="org.eclipse.cdt.core.externalSettings"/>
</cconfiguration>
</storageModule>
<storageModule moduleId="cdtBuildSystem" version="4.0.0">
<project id="afcipm.null.1962733123" name="afcipm"/>
</storageModule>
<storageModule moduleId="org.eclipse.cdt.core.LanguageSettingsProviders"/>
<storageModule moduleId="com.crt.config">
<projectStorage>&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;TargetConfig&gt;
&lt;Properties property_0="" property_2="LPC175x_6x_128.cfx" property_3="NXP" property_4="LPC1764" property_count="5" version="70200"/&gt;
&lt;infoList vendor="NXP"&gt;&lt;info chip="LPC1764" flash_driver="LPC175x_6x_128.cfx" match_id="0x00011922,0x26011922" name="LPC1764" stub="crt_emu_cm3_nxp"&gt;&lt;chip&gt;&lt;name&gt;LPC1764&lt;/name&gt;
&lt;family&gt;LPC17xx&lt;/family&gt;
&lt;vendor&gt;NXP (formerly Philips)&lt;/vendor&gt;
&lt;reset board="None" core="Real" sys="Real"/&gt;
&lt;clock changeable="TRUE" freq="20MHz" is_accurate="TRUE"/&gt;
&lt;memory can_program="true" id="Flash" is_ro="true" type="Flash"/&gt;
&lt;memory id="RAM" type="RAM"/&gt;
&lt;memory id="Periph" is_volatile="true" type="Peripheral"/&gt;
&lt;memoryInstance derived_from="Flash" id="MFlash128" location="0x00000000" size="0x20000"/&gt;
&lt;memoryInstance derived_from="RAM" id="RamLoc16" location="0x10000000" size="0x4000"/&gt;
&lt;memoryInstance derived_from="RAM" id="RamAHB16" location="0x2007c000" size="0x4000"/&gt;
&lt;prog_flash blocksz="0x1000" location="0" maxprgbuff="0x1000" progwithcode="TRUE" size="0x10000"/&gt;
&lt;prog_flash blocksz="0x8000" location="0x10000" maxprgbuff="0x1000" progwithcode="TRUE" size="0x10000"/&gt;
&lt;peripheralInstance derived_from="LPC17_NVIC" determined="infoFile" id="NVIC" location="0xE000E000"/&gt;
&lt;peripheralInstance derived_from="TIMER" determined="infoFile" enable="SYSCTL.PCONP.PCTIM0&amp;amp;0x1" id="TIMER0" location="0x40004000"/&gt;
&lt;peripheralInstance derived_from="TIMER" determined="infoFile" enable="SYSCTL.PCONP.PCTIM1&amp;amp;0x1" id="TIMER1" location="0x40008000"/&gt;
&lt;peripheralInstance derived_from="TIMER" determined="infoFile" enable="SYSCTL.PCONP.PCTIM2&amp;amp;0x1" id="TIMER2" location="0x40090000"/&gt;
&lt;peripheralInstance derived_from="TIMER" determined="infoFile" enable="SYSCTL.PCONP.PCTIM3&amp;amp;0x1" id="TIMER3" location="0x40094000"/&gt;
&lt;peripheralInstance derived_from="LPC17_RIT" determined="infoFile" enable="SYSCTL.PCONP.PCRIT&amp;amp;0x1" id="RIT" location="0x400B0000"/&gt;
&lt;peripheralInstance derived_from="FGPIO" determined="infoFile" enable="SYSCTL.PCONP.PCGPIO&amp;amp;0x1" id="GPIO0" location="0x2009C000"/&gt;
&lt;peripheralInstance derived_from="FGPIO" determined="infoFile" enable="SYSCTL.PCONP.PCGPIO&amp;amp;0x1" id="GPIO1" location="0x2009C020"/&gt;
&lt;peripheralInstance derived_from="FGPIO" determined="infoFile" enable="SYSCTL.PCONP.PCGPIO&amp;amp;0x1" id="GPIO2" location="0x2009C040"/&gt;
&lt;peripheralInstance derived_from="FGPIO" determined="infoFile" enable="SYSCTL.PCONP.PCGPIO&amp;amp;0x1" id="GPIO3" location="0x2009C060"/&gt;
&lt;peripheralInstance derived_from="FGPIO" determined="infoFile" enable="SYSCTL.PCONP.PCGPIO&amp;amp;0x1" id="GPIO4" location="0x2009C080"/&gt;
&lt;peripheralInstance derived_from="LPC17_I2S" determined="infoFile" enable="SYSCTL.PCONP&amp;amp;0x08000000" id="I2S" location="0x400A8000"/&gt;
&lt;peripheralInstance derived_from="LPC17_SYSCTL" determined="infoFile" id="SYSCTL" location="0x400FC000"/&gt;
&lt;peripheralInstance derived_from="LPC17xx_UART" determined="infoFile" enable="SYSCTL.PCONP.PCUART0&amp;amp;0x1" id="UART0" location="0x4000C000"/&gt;
&lt;peripheralInstance derived_from="LPC17xx_UART_MODEM" determined="infoFile" enable="SYSCTL.PCONP.PCUART1&amp;amp;0x1" id="UART1" location="0x40010000"/&gt;
&lt;peripheralInstance derived_from="LPC17xx_UART" determined="infoFile" enable="SYSCTL.PCONP.PCUART2&amp;amp;0x1" id="UART2" location="0x40098000"/&gt;
&lt;peripheralInstance derived_from="LPC17xx_UART" determined="infoFile" enable="SYSCTL.PCONP.PCUART3&amp;amp;0x1" id="UART3" location="0x4009C000"/&gt;
&lt;peripheralInstance derived_from="SPI" determined="infoFile" enable="SYSCTL.PCONP.PCSPI&amp;amp;0x1" id="SPI" location="0x40020000"/&gt;
&lt;peripheralInstance derived_from="LPC17_SSP" determined="infoFile" enable="SYSCTL.PCONP.PCSSP0&amp;amp;0x1" id="SSP0" location="0x40088000"/&gt;
&lt;peripheralInstance derived_from="LPC17_SSP" determined="infoFile" enable="SYSCTL.PCONP.PCSSP1&amp;amp;0x1" id="SSP1" location="0x40030000"/&gt;
&lt;peripheralInstance derived_from="LPC17_ADC" determined="infoFile" enable="SYSCTL.PCONP.PCAD&amp;amp;0x1" id="ADC" location="0x40034000"/&gt;
&lt;peripheralInstance derived_from="LPC17_USBINTST" determined="infoFile" enable="USBCLKCTL.USBClkCtrl&amp;amp;0x12" id="USBINTSTAT" location="0x400fc1c0"/&gt;
&lt;peripheralInstance derived_from="LPC17_USB_CLK_CTL" determined="infoFile" id="USBCLKCTL" location="0x5000cff4"/&gt;
&lt;peripheralInstance derived_from="LPC17_USBDEV" determined="infoFile" enable="USBCLKCTL.USBClkSt&amp;amp;0x12=0x12" id="USBDEV" location="0x5000C200"/&gt;
&lt;peripheralInstance derived_from="LPC17_PWM" determined="infoFile" enable="SYSCTL.PCONP.PWM1&amp;amp;0x1" id="PWM" location="0x40018000"/&gt;
&lt;peripheralInstance derived_from="LPC17_I2C" determined="infoFile" enable="SYSCTL.PCONP.PCI2C0&amp;amp;0x1" id="I2C0" location="0x4001C000"/&gt;
&lt;peripheralInstance derived_from="LPC17_I2C" determined="infoFile" enable="SYSCTL.PCONP.PCI2C1&amp;amp;0x1" id="I2C1" location="0x4005C000"/&gt;
&lt;peripheralInstance derived_from="LPC17_I2C" determined="infoFile" enable="SYSCTL.PCONP.PCI2C2&amp;amp;0x1" id="I2C2" location="0x400A0000"/&gt;
&lt;peripheralInstance derived_from="LPC17_DMA" determined="infoFile" enable="SYSCTL.PCONP.PCGPDMA&amp;amp;0x1" id="DMA" location="0x50004000"/&gt;
&lt;peripheralInstance derived_from="CM3_DCR" determined="infoFile" id="DCR" location="0xE000EDF0"/&gt;
&lt;peripheralInstance derived_from="LPC17_PCB" determined="infoFile" id="PCB" location="0x4002c000"/&gt;
&lt;peripheralInstance derived_from="LPC17_QEI" determined="infoFile" id="QEI" location="0x400bc000"/&gt;
&lt;peripheralInstance derived_from="LPC17_RTC" determined="infoFile" enable="SYSCTL.PCONP.PCRTC&amp;amp;0x1" id="RTC" location="0x40024000"/&gt;
&lt;peripheralInstance derived_from="MPU" determined="infoFile" id="MPU" location="0xE000ED90"/&gt;
&lt;peripheralInstance derived_from="LPC1x_WDT" determined="infoFile" id="WDT" location="0x40000000"/&gt;
&lt;peripheralInstance derived_from="LPC17_ENET" determined="infoFile" enable="SYSCTL.PCONP.PCENET&amp;amp;0x1" id="ENET" location="0x50000000"/&gt;
&lt;peripheralInstance derived_from="LPC17_FLASHCFG" determined="infoFile" id="FLASHACCEL" location="0x400FC000"/&gt;
&lt;peripheralInstance derived_from="GPIO_INT" determined="infoFile" id="GPIOINTMAP" location="0x40028080"/&gt;
&lt;peripheralInstance derived_from="LPC17_CANAFR" determined="infoFile" enable="SYSCTL.PCONP.PCCAN1&amp;amp;0x1|SYSCTL.PCONP.PCCAN2&amp;amp;0x1" id="CANAFR" location="0x4003C000"/&gt;
&lt;peripheralInstance derived_from="LPC17_CANCEN" determined="infoFile" enable="SYSCTL.PCONP.PCCAN1&amp;amp;0x1|SYSCTL.PCONP.PCCAN2&amp;amp;0x1" id="CANCEN" location="0x40040000"/&gt;
&lt;peripheralInstance derived_from="LPC17_CANWAKESLEEP" determined="infoFile" id="CANWAKESLEEP" location="0x400FC110"/&gt;
&lt;peripheralInstance derived_from="LPC17_CANCON" determined="infoFile" enable="SYSCTL.PCONP.PCCAN1&amp;amp;0x1" id="CANCON1" location="0x40044000"/&gt;
&lt;peripheralInstance derived_from="LPC17_CANCON" determined="infoFile" enable="SYSCTL.PCONP.PCCAN2&amp;amp;0x1" id="CANCON2" location="0x40048000"/&gt;
&lt;peripheralInstance derived_from="LPC17_MCPWM" determined="infoFile" enable="SYSCTL.PCONP.PCMCPWM&amp;amp;0x1" id="MCPWM" location="0x400B8000"/&gt;
&lt;peripheralInstance derived_from="LPC17_FMC" determined="infoFile" id="FMC" location="0x40084000"/&gt;
&lt;/chip&gt;
&lt;processor&gt;&lt;name gcc_name="cortex-m3"&gt;Cortex-M3&lt;/name&gt;
&lt;family&gt;Cortex-M&lt;/family&gt;
&lt;/processor&gt;
&lt;link href="nxp_lpcxxxx_peripheral.xme" show="embed" type="simple"/&gt;
&lt;/info&gt;
&lt;/infoList&gt;
&lt;/TargetConfig&gt;</projectStorage>
</storageModule>
<storageModule moduleId="refreshScope"/>
<storageModule moduleId="org.eclipse.cdt.make.core.buildtargets"/>
<storageModule moduleId="scannerConfiguration">
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
<scannerConfigBuildInfo instanceId="0.1161478944">
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
</scannerConfigBuildInfo>
</storageModule>
</cproject>
...@@ -33,17 +33,26 @@ ...@@ -33,17 +33,26 @@
Debug/ Debug/
*.launch *.launch
*.xml *.xml
#.cproject .cproject
#.project .project
#Temporary files #Temporary files
*.swp *.swp
*.map *.map
*~ *~
*#*
*.#*
#Dependency files #Dependency files
*.d *.d
#Binaries #Binaries
*.axf *.axf
*.bin *.bin
\ No newline at end of file
#Cmake file
CMakeFiles/
*.dir/*
Makefile
*cmake_install.cmake
CMakeCache.txt
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>afcipm</name>
<comment></comment>
<projects>
<project>lpc_chip_175x_6x</project>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.cdt.managedbuilder.core.genmakebuilder</name>
<triggers>clean,full,incremental,</triggers>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder</name>
<triggers>full,incremental,</triggers>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.cdt.core.cnature</nature>
<nature>org.eclipse.cdt.managedbuilder.core.managedBuildNature</nature>
<nature>org.eclipse.cdt.managedbuilder.core.ScannerConfigNature</nature>
</natures>
</projectDescription>
# Define minimal required version of CMake.
cmake_minimum_required(VERSION 2.8.7)
# Project definition
project(openMMC C CXX ASM)
# Color definitions
if(NOT WIN32)
string(ASCII 27 Esc)
set(ColourReset "${Esc}[m")
set(ColourBold "${Esc}[1m")
set(Red "${Esc}[31m")
set(Green "${Esc}[32m")
set(Yellow "${Esc}[33m")
set(Blue "${Esc}[34m")
set(Magenta "${Esc}[35m")
set(Cyan "${Esc}[36m")
set(White "${Esc}[37m")
set(BoldRed "${Esc}[1;31m")
set(BoldGreen "${Esc}[1;32m")
set(BoldYellow "${Esc}[1;33m")
set(BoldBlue "${Esc}[1;34m")
set(BoldMagenta "${Esc}[1;35m")
set(BoldCyan "${Esc}[1;36m")
set(BoldWhite "${Esc}[1;37m")
endif()
##
# CMake environment settings
#
#Find a toolchain file
if(NOT CMAKE_TOOLCHAIN_FILE)
message(WARNING "${Yellow}No toolchain configuration file specified. Using default option!${ColourReset}")
include(toolchain/toolchain-arm-none-eabi.cmake)
endif()
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/build_cfg")
set(CMAKE_COLOR_MAKEFILE ON)
set(CMAKE_VERBOSE_MAKEFILE ON)
set(CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS TRUE)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/out)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/lib)
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/lib)
if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE Debug CACHE STRING
"Choose the type of build, options are: none Debug Release Trace."
FORCE)
endif()
# Include board specific code
set(CMAKE_ERROR_FLAGS "-Wall -Wextra -Wpointer-arith -Wno-packed-bitfield-compat -Wno-unused-parameter -Wno-missing-field-initializers")
# Build specific flags
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${CMAKE_ERROR_FLAGS}")
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS} -O0 -g3 -DDEBUG")
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS} -O3")
# When we break up long strings in CMake we get semicolon
# separated lists, undo this here...
string(REGEX REPLACE ";" " " CMAKE_C_FLAGS "${CMAKE_C_FLAGS}")
string(REGEX REPLACE ";" " " CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG}")
string(REGEX REPLACE ";" " " CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE}")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS}" CACHE STRING "")
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG}" CACHE STRING "")
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE}" CACHE STRING "")
set(PROJ_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/main_mmc.c)
add_subdirectory(port/board)
add_subdirectory(port/chip)
add_subdirectory(FreeRTOS)
add_subdirectory(boot)
add_subdirectory(modules)
if(CMAKE_BUILD_TYPE STREQUAL "Trace")
add_subdirectory(trace)
endif()
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DTARGET_CONTROLLER=${TARGET_CONTROLLER} -DTARGET_BOARD_NAME=${TARGET_BOARD_NAME} -DTARGET_BOARD_MAJOR=${TARGET_BOARD_MAJOR} -DTARGET_BOARD_MINOR=${TARGET_BOARD_MINOR} ")
# Libraries path
link_directories(${CMAKE_LIBRARY_OUTPUT_DIRECTORY})
## Create executable
add_executable(${CMAKE_PROJECT_NAME} ${LPC17_SRCS} ${PROJ_SRCS})
set_target_properties(${CMAKE_PROJECT_NAME} PROPERTIES COMPILE_FLAGS ${MODULES_FLAGS})
add_executable(bootloader ${BOOT_SRCS} ${LPC17_SRCS})
# Linker flags
set(CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "")
set_target_properties(${CMAKE_PROJECT_NAME} PROPERTIES
SUFFIX ".axf"
LINK_FLAGS "-T ${CMAKE_SOURCE_DIR}/linker/lpc1764_app.ld -Wl,-Map=${CMAKE_SOURCE_DIR}/linker/lpc1764_app.map" )
set_target_properties(bootloader PROPERTIES
SUFFIX ".axf"
LINK_FLAGS "-T ${CMAKE_SOURCE_DIR}/linker/lpc1764_boot.ld -Wl,-Map=${CMAKE_SOURCE_DIR}/linker/lpc1764_boot.map")
# Headers path
target_include_directories(${CMAKE_PROJECT_NAME} PUBLIC ${PROJ_HDRS})
target_include_directories(bootloader PUBLIC ${PROJ_HDRS})
# Link libraries
target_link_libraries(${CMAKE_PROJECT_NAME} gcc c m FreeRTOS lpcopen)
target_link_libraries(bootloader gcc c m lpcopen)
##Generate .hex file
add_custom_command(TARGET ${CMAKE_PROJECT_NAME} POST_BUILD
COMMAND ${CMAKE_OBJCOPY} -O binary ${CMAKE_PROJECT_NAME}.axf ${CMAKE_PROJECT_NAME}.bin
WORKING_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}
COMMENT "Converting the AXF output to a binary file"
)
add_custom_command(TARGET bootloader POST_BUILD
COMMAND ${CMAKE_OBJCOPY} -O binary bootloader.axf bootloader.bin
WORKING_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}
COMMENT "Converting the AXF output to a binary file"
)
##Program command
set(LPCXPRESSO_PATH /usr/local/lpcxpresso_7.8.0_426/lpcxpresso/)
find_program(DFU_UTIL dfu-util)
find_program(NXP_PROG crt_emu_cm3_nxp PATHS ${LPCXPRESSO_PATH}/bin NO_DEFAULT_PATH)
if(NOT DFU_UTIL)
message(WARNING "${ColourBold}${Red}Dfu-util not found! Can't boot the LPCLink board!${ColourReset}")
elseif(NOT NXP_PROG)
message(WARNING "${ColourBold}${Red}crt_emu_cm3_nxp not found! Can't program the LPC chip!${ColourReset}")
else()
# Boot the programmer
execute_process(
COMMAND ${DFU_UTIL} -d 0x471:0xdf55 -c 0 -t 2048 -R -D ${LPCXPRESSO_PATH}/bin/LPCXpressoWIN.enc
ERROR_QUIET
)
# Program the chip (available only for LPC1764 so far)
add_custom_target(program_boot
WORKING_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/
DEPENDS bootloader
COMMAND ${NXP_PROG} -wire=winusb -p${TARGET_CONTROLLER} -g -flash-load=bootloader.bin -load-base=0x0000
)
add_custom_target(program_app
WORKING_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/
DEPENDS ${CMAKE_PROJECT_NAME}
COMMAND ${NXP_PROG} -wire=winusb -p${TARGET_CONTROLLER} -g -flash-load-exec=${CMAKE_PROJECT_NAME}.bin -load-base=0x2000
)
add_custom_target(program_all
WORKING_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/
DEPENDS ${CMAKE_PROJECT_NAME} bootloader
COMMAND ${NXP_PROG} -wire=winusb -p${TARGET_CONTROLLER} -flash-mass-erase
COMMAND make -C ${CMAKE_SOURCE_DIR} program_boot
COMMAND make -C ${CMAKE_SOURCE_DIR} program_app
)
endif()
# Build FreeRTOS library
set(FREERTOS_INC ${CMAKE_CURRENT_SOURCE_DIR}/include)
include_directories(${PROJ_HDRS})
include_directories(${FREERTOS_INC})
set(PROJ_HDRS ${PROJ_HDRS} ${FREERTOS_INC} PARENT_SCOPE)
set(LIBFREERTOS_SRCS
list.c
queue.c
timers.c
port.c
tasks.c
heap_4.c
heap_2.c
event_groups.c
)
add_library(FreeRTOS STATIC ${LIBFREERTOS_SRCS})
...@@ -349,6 +349,47 @@ BlockLink_t *pxLink; ...@@ -349,6 +349,47 @@ BlockLink_t *pxLink;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
#include "string.h"
void *pvPortCalloc(size_t count, size_t size)
{
void *p;
/* allocate 'count' objects of size 'size' */
p = pvPortMalloc(count * size);
if (p) {
/* zero the memory */
memset(p, 0, count * size);
}
return p;
}
void *calloc(size_t count, size_t nbytes) __attribute__((alias("pvPortCalloc")));
/*-----------------------------------------------------------*/
void *pvPortRealloc(void *mem, size_t newsize)
{
void *p;
p = pvPortMalloc(newsize);
if (p) {
/* Copy the contents of the old region */
if (mem != NULL) {
memcpy(p, mem, newsize);
vPortFree(mem);
}
}
return p;
}
void *realloc(void *ptr, size_t nbytes) __attribute__((alias("pvPortRealloc")));
/*-----------------------------------------------------------*/
/*-----------------------------------------------------------*/
size_t xPortGetFreeHeapSize( void ) size_t xPortGetFreeHeapSize( void )
{ {
return xFreeBytesRemaining; return xFreeBytesRemaining;
......
...@@ -57,7 +57,7 @@ licensing and training services. ...@@ -57,7 +57,7 @@ licensing and training services.
#define configMINIMAL_STACK_SIZE ( ( unsigned short ) 150 ) #define configMINIMAL_STACK_SIZE ( ( unsigned short ) 150 )
#define configTOTAL_HEAP_SIZE ( ( size_t ) ( 0x4000 ) ) #define configTOTAL_HEAP_SIZE ( ( size_t ) ( 0x4000 ) )
#define configMAX_TASK_NAME_LEN ( 12 ) #define configMAX_TASK_NAME_LEN ( 12 )
#define configUSE_TRACE_FACILITY 0 #define configUSE_TRACE_FACILITY 1
#define configUSE_16_BIT_TICKS 0 #define configUSE_16_BIT_TICKS 0
#define configIDLE_SHOULD_YIELD 0 #define configIDLE_SHOULD_YIELD 0
#define configUSE_CO_ROUTINES 0 #define configUSE_CO_ROUTINES 0
...@@ -68,7 +68,7 @@ licensing and training services. ...@@ -68,7 +68,7 @@ licensing and training services.
#define configCHECK_FOR_STACK_OVERFLOW 1 #define configCHECK_FOR_STACK_OVERFLOW 1
#define configUSE_RECURSIVE_MUTEXES 0 #define configUSE_RECURSIVE_MUTEXES 0
#define configQUEUE_REGISTRY_SIZE 3 #define configQUEUE_REGISTRY_SIZE 3
#define configGENERATE_RUN_TIME_STATS 0 #define configGENERATE_RUN_TIME_STATS 1
#define configUSE_MALLOC_FAILED_HOOK 0 #define configUSE_MALLOC_FAILED_HOOK 0
#define configENABLE_BACKWARD_COMPATIBILITY 1 #define configENABLE_BACKWARD_COMPATIBILITY 1
#define configUSE_APPLICATION_TASK_TAG 0 #define configUSE_APPLICATION_TASK_TAG 0
...@@ -77,6 +77,7 @@ licensing and training services. ...@@ -77,6 +77,7 @@ licensing and training services.
#define configAPPLICATION_ALLOCATED_HEAP 1 #define configAPPLICATION_ALLOCATED_HEAP 1
#define USE_HEAP_4 #define USE_HEAP_4
void vAssertCalled( char* file, uint32_t line);
#define configASSERT( x ) if( ( x ) == 0 ) { vAssertCalled( __FILE__, __LINE__ );} #define configASSERT( x ) if( ( x ) == 0 ) { vAssertCalled( __FILE__, __LINE__ );}
#if (configGENERATE_RUN_TIME_STATS == 1) #if (configGENERATE_RUN_TIME_STATS == 1)
...@@ -92,7 +93,7 @@ extern void vConfigureTimerForRunTimeStats( void ); ...@@ -92,7 +93,7 @@ extern void vConfigureTimerForRunTimeStats( void );
#define INCLUDE_vTaskPrioritySet 1 #define INCLUDE_vTaskPrioritySet 1
#define INCLUDE_uxTaskPriorityGet 0 #define INCLUDE_uxTaskPriorityGet 0
#define INCLUDE_vTaskDelete 1 #define INCLUDE_vTaskDelete 1
#define INCLUDE_vTaskCleanUpResources 0 #define INCLUDE_vTaskCleanUpResources 1
#define INCLUDE_vTaskSuspend 1 #define INCLUDE_vTaskSuspend 1
#define INCLUDE_vTaskDelayUntil 1 #define INCLUDE_vTaskDelayUntil 1
#define INCLUDE_vTaskDelay 1 #define INCLUDE_vTaskDelay 1
......
...@@ -162,6 +162,8 @@ void vPortDefineHeapRegions( const HeapRegion_t * const pxHeapRegions ); ...@@ -162,6 +162,8 @@ void vPortDefineHeapRegions( const HeapRegion_t * const pxHeapRegions );
*/ */
void *pvPortMalloc( size_t xSize ) PRIVILEGED_FUNCTION; void *pvPortMalloc( size_t xSize ) PRIVILEGED_FUNCTION;
void vPortFree( void *pv ) PRIVILEGED_FUNCTION; void vPortFree( void *pv ) PRIVILEGED_FUNCTION;
void *pvPortCalloc(size_t count, size_t size) PRIVILEGED_FUNCTION;
void *pvPortRealloc(void *mem, size_t newsize) PRIVILEGED_FUNCTION;
void vPortInitialiseBlocks( void ) PRIVILEGED_FUNCTION; void vPortInitialiseBlocks( void ) PRIVILEGED_FUNCTION;
size_t xPortGetFreeHeapSize( void ) PRIVILEGED_FUNCTION; size_t xPortGetFreeHeapSize( void ) PRIVILEGED_FUNCTION;
size_t xPortGetMinimumEverFreeHeapSize( void ) PRIVILEGED_FUNCTION; size_t xPortGetMinimumEverFreeHeapSize( void ) PRIVILEGED_FUNCTION;
......
TOOLCHAIN = arm-none-eabi-
CC = $(TOOLCHAIN)gcc
AR = $(TOOLCHAIN)ar
OBJCOPY = $(TOOLCHAIN)objcopy
PROJ = afcipm
MAKEFILE = Makefile
MAKE = make
MCPU = cortex-m3
LIBDIR = lib
BUILDDIR = out
#Used for program operation (LPCLink specific software)
LPCXPRESSO_PATH=/usr/local/lpcxpresso*/lpcxpresso
#Flags to be passed on to gcc
DEFS = -DDEBUG -DCORE_M3 -D__CODE_RED -D__USE_LPCOPEN -DNO_BOARD_LIB -D__LPC17XX__ -D__NEWLIB__
LD_SCRIPT = linker/lpc1764.ld
MAP = linker/afcipm.map
LD_FLAGS = -T $(LD_SCRIPT) -Xlinker -Map=$(MAP)
LD_FLAGS += -Xlinker --gc-sections
LD_FLAGS += -mcpu=$(MCPU) -mthumb
LD_FLAGS += --specs=nosys.specs
LPCOPEN_LIBNAME = lpcopen
LPCOPEN_LIBFILE = $(LIBDIR)/lib$(LPCOPEN_LIBNAME).a
LPCOPEN_PATH = ./port/nxp/lpc17xx/lpcopen
LPCOPEN_SRCPATH = $(LPCOPEN_PATH)/src
LPCOPEN_SRC = $(shell find $(LPCOPEN_SRCPATH) -name '*.c')
LPCOPEN_INCPATH = $(LPCOPEN_PATH)/inc
LPCOPEN_OBJS = $(LPCOPEN_SRC:%.c=%.o)
FREERTOS_LIBNAME = freertos
FREERTOS_LIBFILE = $(LIBDIR)/lib$(FREERTOS_LIBNAME).a
FREERTOS_PATH = ./FreeRTOS
FREERTOS_SRCPATH = $(FREERTOS_PATH)
FREERTOS_SRC = $(shell find $(FREERTOS_SRCPATH) -name '*.c')
FREERTOS_INCPATH = $(FREERTOS_PATH)/include
FREERTOS_OBJS = $(FREERTOS_SRC:%.c=%.o)
INCLUDES = -I./
INCLUDES += -I./board/afcv3
INCLUDES += -I./port/nxp/lpc17xx
INCLUDES += -I./modules
INCLUDES += -I./trace/Include
INCLUDES += -I./modules/sensors
INCLUDES += -I$(LPCOPEN_INCPATH)
INCLUDES += -I$(FREERTOS_INCPATH)
EXTRA_CFLAGS = -Wall -O0 -g3 -std=gnu99
CFLAGS = $(DEFS) $(INCLUDES)
CFLAGS += -mcpu=$(MCPU) -mthumb
CFLAGS += -Wno-packed-bitfield-compat
CFLAGS += -fno-builtin -ffunction-sections -fdata-sections -fno-strict-aliasing -fmessage-length=0 -nostdlib
CFLAGS += $(EXTRA_CFLAGS)
LIBS += -lgcc -lc -lm -l$(FREERTOS_LIBNAME) -l$(LPCOPEN_LIBNAME)
DEPS = -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@:%.o=%.o)" -MT"$(@:%.o=%.d)"
PROJ_SRCDIR = ./
PROJ_SRC = $(shell find $(PROJ_SRCDIR) -type d \( -path $(FREERTOS_PATH) -o -path $(LPCOPEN_PATH) \) -prune -o -name '*.c' -print)
PROJ_OBJS = $(PROJ_SRC:%.c=%.o)
.PRECIOUS: %.axf %.bin
all: $(PROJ).bin
folders:
@mkdir -p $(LIBDIR)
@mkdir -p $(BUILDDIR)
%.bin: $(BUILDDIR)/%.axf
@echo 'Creating Binary file from .axf'
$(OBJCOPY) -O binary $< $(BUILDDIR)/$@
@echo 'Binary file created succesfully!'
@echo ' '
#Linker
%.axf: folders $(FREERTOS_LIBFILE) $(LPCOPEN_LIBFILE) $(PROJ_OBJS)
@echo 'Invoking MCU Linker'
$(CC) $(LD_FLAGS) -o $(BUILDDIR)/$(notdir $@) $(PROJ_OBJS) -L$(LIBDIR) $(LIBS)
@echo '$@ linked successfully!'
@echo ' '
#Sources Compile
%.o: %.c
@echo 'Building $< '
$(CC) $(CFLAGS) $(DEPS) -o $@ -c $<
-include $(@:%.o=%.d)
@echo ' $< built successfully!'
@echo ' '
#Archiver for FreeRTOS objects
$(FREERTOS_LIBFILE): $(FREERTOS_OBJS)
@echo 'Archiving $@ objs'
$(AR) -r $@ $(FREERTOS_OBJS)
@echo 'Library $@ successfully created'
@echo ' '
#Archiver for LPCOpen objects
$(LPCOPEN_LIBFILE): $(LPCOPEN_OBJS)
@echo 'Archiving $@ objs'
$(AR) -r $@ $(LPCOPEN_OBJS)
@echo 'Library $@ successfully created'
@echo ' '
#Other targets
clean:
@rm -rf $(PROJ_OBJS) $(PROJ_OBJS:%.o=%.d) *.map
@rm -rf $(BUILDDIR)
mrproper: clean
@rm -rf $(LPCOPEN_OBJS) $(LPCOPEN_OBJS:%.o=%.d)
@rm -rf $(FREERTOS_OBJS) $(FREERTOS_OBJS:%.o=%.d)
@rm -rf $(LIBDIR)
boot:
@echo 'Booting LPCLink...'
$(LPCXPRESSO_PATH)/bin/dfu-util -d 0x471:0xdf55 -c 0 -t 2048 -R -D $(LPCXPRESSO_PATH)/bin/LPCXpressoWIN.enc
@echo 'LPCLink booted!'
@echo ' '
program:
@if [ ! -f $(BUILDDIR)/$(PROJ).axf ]; then \
$(MAKE) $(PROJ).axf; \
fi
@$(MAKE) -i boot
@echo 'Programing Flash...'
#Program flash and reset chip
$(LPCXPRESSO_PATH)/bin/crt_emu_cm3_nxp -wire=winusb -pLPC1764 -flash-load-exec=$(BUILDDIR)/$(PROJ).axf
@echo 'Programed Successfully!'
@echo ' '
#Debug print
print-%: ; @echo $*=$($*)
.PHONY: all clean mrproper boot program folders
# AFCIPM # openMMC
MMC firmware for AFC boards Open Source modular IPM Controller firmware
## Installation: ## Installation:
To compile this firmware, it is necessary to install **`GCC ARM Embedded`**, a specific toolchain to Cortex-M and Cortex-R processors. The following packages are needed in your system in order to compile the firmware:
You can download it's binary and install yourself: - **gcc-arm-none-eabi**
* https://launchpad.net/gcc-arm-embedded/+download - **cmake**
- **cmake-gui** (Optional)
or run the following command: **gcc-arm-none-eabi** can be installed from the pre-compiled files found at: https://launchpad.net/gcc-arm-embedded/+download
or you can run the following command under Ubuntu:
sudo apt-get install gcc-arm-none-eabi sudo apt-get install gcc-arm-none-eabi
Next step is to clone this repository into your workspace.
git clone https://github.com/lnls-dig/openMMC
## Compilation ## Compilation
Go to the repository folder Go to the repository folder
cd afcipm cd /path/to/repo/
If this is the first time compiling this firmware, run CMake configuration scripts
Compile the firmware cmake .
make all You can set your board options in the file `build_cfg/config.cmake`. You can change the Controller, Board name, version and select which modules you want to be included in your compilation.
It will create a `.axf` file and a `.bin` file, which you can use to program your processor. After changing the desired options, run the CMake configuration command again (the CMakeCache file will not be edited by this command) and compile the firmware:
If you want to create only a `.bin` file, or specify a different output name, run make -s
make <output_name>.bin *NOTE: The compiler will return several warnings, most of them are regarding the LPCOpen libraries and do not affect the library functionality.*
Both a `.axf` file and a `.bin` file will be generated in the `out` folder. You can use any one you prefer to program your processor.
To clean the compilation files (binaries, objects and dependence files), just run To clean the compilation files (binaries, objects and dependence files), just run
...@@ -33,7 +43,17 @@ To clean the compilation files (binaries, objects and dependence files), just ru ...@@ -33,7 +43,17 @@ To clean the compilation files (binaries, objects and dependence files), just ru
## Programming LPC1764 ## Programming LPC1764
If you own a *LPCLink* board, you can use it to program the LPC1764 processor via its JTAG interface If you own a *LPCLink* board, you can use it to program the LPC1764 processor via its JTAG interface
make program To transfer only the application firmware, run
make program_app
To transfer only the bootloader firmware, run
make program_boot
If you want to erase the whole Flash and copy both firmwares:
make program_all
**NOTE**: In this case you must have the LPCXpresso installed in your machine, since we need to use some initialization scripts that they provide. **NOTE**: In this case you must have the LPCXpresso installed in your machine, since we need to use some initialization scripts that they provide.
**NOTE 2**: We only have linker scripts to LPC1764, so if you wish to compile to a different target, you'll have to change the `afcipm_mem.ld` file, which defines the memory regions, otherwise you'll run into some HardFault errors. **NOTE 2**: We only have linker scripts to LPC1764, so if you wish to compile to a different target, you'll have to change the `linker\lpc1764_boot.ld` and `linker\lpc1764_app.ld` files, which defines the memory regions, otherwise you'll run into some HardFault errors.
#include "port.h"
#include "pin_mapping.h"
#include "ad84xx.h"
void dac_vadj_init( void )
{
gpio_set_pin_dir( GPIO_DAC_VADJ_RST_PORT, GPIO_DAC_VADJ_RST_PIN, OUTPUT);
gpio_set_pin_dir( GPIO_DAC_VADJ_CSN_PORT, GPIO_DAC_VADJ_CSN_PIN, OUTPUT);
gpio_set_pin_state( GPIO_DAC_VADJ_RST_PORT, GPIO_DAC_VADJ_RST_PIN, LOW);
spi_config( DAC_VADJ_SPI_SPEED, DAC_VADJ_FRAME_SIZE, SPI_MASTER, SPI_POLLING );
gpio_set_pin_state( GPIO_DAC_VADJ_RST_PORT, GPIO_DAC_VADJ_RST_PIN, HIGH);
}
void dac_vadj_config( uint8_t addr, uint8_t val )
{
uint8_t data[2] = { (val), (addr & 0x3) };
spi_assertSSEL();
spi_write( &data, sizeof(data) );
spi_deassertSSEL();
}
#ifndef AD84XX_H_
#define AD84XX_H_
#define DAC_VADJ_SPI_SPEED 10000000
#define DAC_VADJ_FRAME_SIZE 10
void dac_vadj_init( void );
void dac_vadj_config( uint8_t addr, uint8_t val );
#endif
#ifndef FPGA_SPI_H_
#define FPGA_SPI_H_
#define FPGA_SPI 0
#define FPGA_BITRATE 10000000
#define FPGA_UPDATE_RATE 5000 // in ms
#define FPGA_MEM_ADDR_MAX 0xFF
#define WR_COMMAND 0x80
#define RD_COMMAND 0x00
#define NO_DIAG 0x00
#define FPGA_TEMP_DEVID 0x01
#define FMC1_TEMP_DEVID 0x02
#define FMC2_TEMP_DEVID 0x03
#define DCDC_TEMP_DEVID 0x04
#define SDRAM_TEMP_DEVID 0x05
#define FMC1_12V_CURR_DEVID 0x06
#define FMC1_P3V3_CURR_DEVID 0x07
#define FMC1_VADJ_CURR_DEVID 0x08
#define FMC2_12V_CURR_DEVID 0x09
#define FMC2_P3V3_CURR_DEVID 0x0A
#define FMC2_VADJ_CURR_DEVID 0x0B
#define FMC1_12V_DEVID 0x0C
#define FMC1_P3V3_DEVID 0x0D
#define FMC1_VADJ_DEVID 0x0E
#define FMC2_12V_DEVID 0x0F
#define FMC2_P3V3_DEVID 0x10
#define FMC2_VADJ_DEVID 0x11
typedef struct {
#ifdef BF_MS_FIRST
uint8_t dev_id;
uint32_t measure:24;
#else
uint32_t measure:24;
uint8_t dev_id;
#endif
} t_sensor_diag;
typedef struct __attribute__ ((__packed__)) {
#ifdef BF_MS_FIRST
uint32_t reserved:26,
fmc2_pg_c2m:1,
fmc1_pg_c2m:1,
fmc2_pg_m2c:1,
fmc1_pg_m2c:1,
fmc2_prsnt_m2c_n:1,
fmc1_prsnt_m2c_n:1;
#else
uint32_t fmc1_prsnt_m2c_n:1,
fmc2_prsnt_m2c_n:1,
fmc1_pg_m2c:1,
fmc2_pg_m2c:1,
fmc1_pg_c2m:1,
fmc2_pg_c2m:1,
reserved:26;
#endif
} t_fmc_diag;
#include "sdr.h"
/* AFC diagnostic struct sent to FPGA via SPI */
typedef struct __attribute__ ((__packed__)) {
uint32_t cardID[4];
uint32_t slot_id:16,
ipmi_addr:16;
uint32_t data_valid;
t_sensor_diag sensor[NUM_SENSOR];
t_fmc_diag fmc_slot;
} board_diagnostic;
typedef union {
board_diagnostic info;
uint32_t buffer[sizeof(board_diagnostic)/sizeof(uint32_t)];
} t_board_diagnostic;
uint8_t cmpBuffs(uint32_t *buf_a, uint32_t len_a, uint32_t *bufb, uint32_t len_b);
void vTaskFPGA_COMM( void * Parameters );
void init_fpga_spi( void );
void init_diag_struct( board_diagnostic * diag );
#endif
set(BOOT_PATH ${CMAKE_CURRENT_SOURCE_DIR})
set(BOOT_SRCS ${BOOT_SRCS} ${BOOT_PATH}/boot.c )
set(BOOT_SRCS ${BOOT_SRCS} PARENT_SCOPE)
set(PROJ_HDRS ${PROJ_HDRS} ${BOOT_PATH} PARENT_SCOPE)
#include "chip.h"
#include "boot.h"
#include "iap.h"
int main (void)
{
SystemCoreClockUpdate();
Bool upgrade = FALSE;
uint32_t upgr_fw_id, user_fw_id;
Chip_GPIO_Init(LPC_GPIO);
Chip_GPIO_SetPinDIROutput(LPC_GPIO, 1, 9);
user_fw_id = *(uint32_t*)USER_FLASH_ID_ADDR;
upgr_fw_id = *(uint32_t*)UPGRADE_FLASH_ID_ADDR;
//if(user_fw_id == 0xFFFFFFFF || ((upgr_fw_id != 0xFFFFFFFF) && (user_fw_id < upgr_fw_id))) {
if(upgr_fw_id != 0xFFFFFFFF) {
upgrade = TRUE;
Chip_GPIO_SetPinState(LPC_GPIO, 1, 9, 0 );
}
if (upgrade) {
update_firmware();
}
execute_user_code();
while (1);
}
void program_page( uint32_t address, uint32_t * data, uint32_t size )
{
uint32_t sector_start = (address & 0xFF000) >> 12;
uint32_t sector_end = ((address+size) & 0xFF000) >> 12;
if (size % 256) {
/* Data should be a 256 byte boundary */
return;
}
if (Chip_IAP_PreSectorForReadWrite( sector_start, sector_end ) != IAP_CMD_SUCCESS) {
return;
}
Chip_IAP_CopyRamToFlash( address, data, size );
}
void erase_sector( uint32_t sector_start, uint32_t sector_end )
{
if (Chip_IAP_PreSectorForReadWrite( sector_start, sector_end ) != IAP_CMD_SUCCESS) {
return;
}
Chip_IAP_EraseSector( sector_start, sector_end );
}
void execute_user_code( void )
{
USER_ENTRY_PFN user_entry;
user_entry = (USER_ENTRY_PFN)*((uint32_t*)(USER_FLASH_START_ADDR +4));
if (user_entry) {
(user_entry)();
}
}
void update_firmware( void )
{
uint32_t dst = USER_FLASH_START_ADDR;
uint32_t *src = (uint32_t *)UPGRADE_FLASH_START_ADDR;
uint32_t page[64];
for(uint8_t j=0; j<(sizeof(page)/sizeof(uint32_t)); j++) {
page[j] = 0xFFFFFFFF;
}
uint32_t fw_size = USER_FLASH_END_ADDR - USER_FLASH_START_ADDR;
uint32_t offset;
erase_sector( USER_FLASH_START_SECTOR , USER_FLASH_END_SECTOR );
for ( offset = 0; offset < fw_size; dst += sizeof(page)) {
/* Populate a page from source address */
for (uint8_t i = 0; i<sizeof(page)/4; i++, src++, offset+=4 ) {
page[i] = *src;
}
/* Program it into dst */
program_page( dst, page, sizeof(page) );
/* Reset the data in local storage */
for(uint8_t j=0; j<(sizeof(page)/sizeof(uint32_t)); j++) {
page[j] = 0xFFFFFFFF;
}
}
//erase_sector( UPGRADE_FLASH_START_SECTOR , UPGRADE_FLASH_END_SECTOR );
}
#define USER_FLASH_START_ADDR (0x2000)
#define USER_FLASH_START_SECTOR (0x2)
#define USER_FLASH_END_ADDR (0x10000)
#define USER_FLASH_END_SECTOR (0xF)
/* Last 4 bytes are reserved for Firmware Version ID */
#define USER_FLASH_ID_ADDR (0xFFFC)
#define UPGRADE_FLASH_START_ADDR (0x10000)
#define UPGRADE_FLASH_START_SECTOR (0x10)
#define UPGRADE_FLASH_END_ADDR (0x1E000)
#define UPGRADE_FLASH_END_SECTOR (0x11)
/* Last 4 bytes are reserved for Firmware Version ID */
#define UPGRADE_FLASH_ID_ADDR (0x1DFFC)
typedef void (*USER_ENTRY_PFN)();
void erase_sector( uint32_t sector_start, uint32_t sector_end );
void execute_user_code( void );
void update_firmware( void );
MEMORY
{
/* Define each memory region */
/* First 8kB are reserved for bootloader */
/* Last 2 sectors (32kB each) are reserved for firmware upgrade */
MFlash128 (rx) : ORIGIN = 0x2000, LENGTH = 0xE000 /* 56K bytes */
RamLoc16 (rwx) : ORIGIN = 0x10000000, LENGTH = 0x4000 /* 16K bytes */
RamAHB16 (rwx) : ORIGIN = 0x2007c000, LENGTH = 0x4000 /* 16K bytes */
}
/* Define a symbol for the top of each memory region */
__top_MFlash128 = 0x2000 + 0xE000;
__top_RamLoc16 = 0x10000000 + 0x4000;
__top_RamAHB16 = 0x2007c000 + 0x4000;
ENTRY(ResetISR)
SECTIONS
{
/* MAIN TEXT SECTION */
.text : ALIGN(4)
{
FILL(0xff)
__vectors_start__ = ABSOLUTE(.) ;
KEEP(*(.isr_vector))
/* Global Section Table */
. = ALIGN(4) ;
__section_table_start = .;
__data_section_table = .;
LONG(LOADADDR(.data));
LONG( ADDR(.data));
LONG( SIZEOF(.data));
LONG(LOADADDR(.data_RAM2));
LONG( ADDR(.data_RAM2));
LONG( SIZEOF(.data_RAM2));
__data_section_table_end = .;
__bss_section_table = .;
LONG( ADDR(.bss));
LONG( SIZEOF(.bss));
LONG( ADDR(.bss_RAM2));
LONG( SIZEOF(.bss_RAM2));
__bss_section_table_end = .;
__section_table_end = . ;
/* End of Global Section Table */
*(.after_vectors*)
} >MFlash128
.text : ALIGN(4)
{
*(.text*)
*(.rodata .rodata.* .constdata .constdata.*)
/* . = ALIGN(4); */
} > MFlash128
.ipmi_handlers : ALIGN(32)
{
_ipmi_handlers = .;
KEEP(*(.ipmi_handlers))
_eipmi_handlers = .;
} > MFlash128
/*
* for exception handling/unwind - some Newlib functions (in common
* with C++ and STDC++) use this.
*/
.ARM.extab : ALIGN(4)
{
*(.ARM.extab* .gnu.linkonce.armextab.*)
} > MFlash128
__exidx_start = .;
.ARM.exidx : ALIGN(4)
{
*(.ARM.exidx* .gnu.linkonce.armexidx.*)
} > MFlash128
__exidx_end = .;
_etext = .;
/* DATA section for RamAHB16 */
.data_RAM2 : ALIGN(4)
{
FILL(0xff)
PROVIDE(__start_data_RAM2 = .) ;
*(.ramfunc.$RAM2)
*(.ramfunc.$RamAHB16)
*(.data.$RAM2*)
*(.data.$RamAHB16*)
. = ALIGN(4) ;
PROVIDE(__end_data_RAM2 = .) ;
} > RamAHB16 AT>MFlash128
/* MAIN DATA SECTION */
.uninit_RESERVED : ALIGN(4)
{
KEEP(*(.bss.$RESERVED*))
. = ALIGN(4) ;
_end_uninit_RESERVED = .;
} > RamLoc16
/* Main DATA section (RamLoc16) */
.data : ALIGN(4)
{
FILL(0xff)
_data = . ;
*(vtable)
*(.ramfunc*)
*(.data*)
. = ALIGN(4) ;
_edata = . ;
} > RamLoc16 AT>MFlash128
/* BSS section for RamAHB16 */
.bss_RAM2 : ALIGN(4)
{
PROVIDE(__start_bss_RAM2 = .) ;
*(.bss.$RAM2*)
*(.bss.$RamAHB16*)
. = ALIGN(4) ;
PROVIDE(__end_bss_RAM2 = .) ;
} > RamAHB16
/* MAIN BSS SECTION */
.bss : ALIGN(4)
{
_bss = .;
*(.bss*)
*(COMMON)
. = ALIGN(4) ;
_ebss = .;
PROVIDE(end = .);
} > RamLoc16
/* NOINIT section for RamAHB16 */
.noinit_RAM2 (NOLOAD) : ALIGN(4)
{
*(.noinit_RAM2*)
*(.noinit_RamAHB16*)
. = ALIGN(4) ;
} > RamAHB16
/* DEFAULT NOINIT SECTION */
.noinit (NOLOAD): ALIGN(4)
{
_noinit = .;
*(.noinit*)
. = ALIGN(4) ;
_end_noinit = .;
} > RamLoc16
PROVIDE(_pvHeapStart = DEFINED(__user_heap_base) ? __user_heap_base : .);
PROVIDE(_vStackTop = DEFINED(__user_stack_top) ? __user_stack_top : __top_RamLoc16 - 0);
}
/* MEMORY
* GENERATED FILE - DO NOT EDIT {
* (c) Code Red Technologies Ltd, 2008-13 /* Define each memory region */
* (c) NXP Semiconductors 2013-2015 /* First 8kB are reserved for bootloader */
* Generated linker script file for LPC1764 MFlash128 (rx) : ORIGIN = 0x0000, LENGTH = 0x2000 /* 8K bytes */
* Created from generic_c.ld (7.8.0 ()) RamLoc16 (rwx) : ORIGIN = 0x10000000, LENGTH = 0x4000 /* 16K bytes */
* By LPCXpresso v7.8.0 [Build 426] [2015-05-28] on Thu Jul 30 09:03:05 BRT 2015 RamAHB16 (rwx) : ORIGIN = 0x2007c000, LENGTH = 0x4000 /* 16K bytes */
*/ }
/* Define a symbol for the top of each memory region */
/* Memory spaces definitions */ __top_MFlash128 = 0x0000 + 0x2000;
INCLUDE "linker/lpc1764_mem.ld" __top_RamLoc16 = 0x10000000 + 0x4000;
__top_RamAHB16 = 0x2007c000 + 0x4000;
ENTRY(ResetISR) ENTRY(ResetISR)
SECTIONS SECTIONS
{ {
/* MAIN TEXT SECTION */ /* MAIN TEXT SECTION */
.text : ALIGN(4) .text : ALIGN(4)
{ {
FILL(0xff) FILL(0xff)
__vectors_start__ = ABSOLUTE(.) ; __vectors_start__ = ABSOLUTE(.) ;
KEEP(*(.isr_vector)) KEEP(*(.isr_vector))
/* Global Section Table */ /* Global Section Table */
. = ALIGN(4) ; . = ALIGN(4) ;
__section_table_start = .; __section_table_start = .;
...@@ -41,12 +42,11 @@ SECTIONS ...@@ -41,12 +42,11 @@ SECTIONS
__bss_section_table_end = .; __bss_section_table_end = .;
__section_table_end = . ; __section_table_end = . ;
/* End of Global Section Table */ /* End of Global Section Table */
*(.after_vectors*) *(.after_vectors*)
} >MFlash128 } >MFlash128
.text : ALIGN(4) .text : ALIGN(4)
{ {
*(.text*) *(.text*)
...@@ -61,13 +61,13 @@ SECTIONS ...@@ -61,13 +61,13 @@ SECTIONS
*/ */
.ARM.extab : ALIGN(4) .ARM.extab : ALIGN(4)
{ {
*(.ARM.extab* .gnu.linkonce.armextab.*) *(.ARM.extab* .gnu.linkonce.armextab.*)
} > MFlash128 } > MFlash128
__exidx_start = .; __exidx_start = .;
.ARM.exidx : ALIGN(4) .ARM.exidx : ALIGN(4)
{ {
*(.ARM.exidx* .gnu.linkonce.armexidx.*) *(.ARM.exidx* .gnu.linkonce.armexidx.*)
} > MFlash128 } > MFlash128
__exidx_end = .; __exidx_end = .;
...@@ -76,18 +76,17 @@ SECTIONS ...@@ -76,18 +76,17 @@ SECTIONS
/* DATA section for RamAHB16 */ /* DATA section for RamAHB16 */
.data_RAM2 : ALIGN(4) .data_RAM2 : ALIGN(4)
{ {
FILL(0xff) FILL(0xff)
PROVIDE(__start_data_RAM2 = .) ; PROVIDE(__start_data_RAM2 = .) ;
*(.ramfunc.$RAM2) *(.ramfunc.$RAM2)
*(.ramfunc.$RamAHB16) *(.ramfunc.$RamAHB16)
*(.data.$RAM2*) *(.data.$RAM2*)
*(.data.$RamAHB16*) *(.data.$RamAHB16*)
. = ALIGN(4) ; . = ALIGN(4) ;
PROVIDE(__end_data_RAM2 = .) ; PROVIDE(__end_data_RAM2 = .) ;
} > RamAHB16 AT>MFlash128 } > RamAHB16 AT>MFlash128
/* MAIN DATA SECTION */ /* MAIN DATA SECTION */
.uninit_RESERVED : ALIGN(4) .uninit_RESERVED : ALIGN(4)
{ {
...@@ -96,27 +95,26 @@ SECTIONS ...@@ -96,27 +95,26 @@ SECTIONS
_end_uninit_RESERVED = .; _end_uninit_RESERVED = .;
} > RamLoc16 } > RamLoc16
/* Main DATA section (RamLoc16) */
/* Main DATA section (RamLoc16) */ .data : ALIGN(4)
.data : ALIGN(4) {
{ FILL(0xff)
FILL(0xff) _data = . ;
_data = . ; *(vtable)
*(vtable) *(.ramfunc*)
*(.ramfunc*) *(.data*)
*(.data*) . = ALIGN(4) ;
. = ALIGN(4) ; _edata = . ;
_edata = . ; } > RamLoc16 AT>MFlash128
} > RamLoc16 AT>MFlash128
/* BSS section for RamAHB16 */ /* BSS section for RamAHB16 */
.bss_RAM2 : ALIGN(4) .bss_RAM2 : ALIGN(4)
{ {
PROVIDE(__start_bss_RAM2 = .) ; PROVIDE(__start_bss_RAM2 = .) ;
*(.bss.$RAM2*) *(.bss.$RAM2*)
*(.bss.$RamAHB16*) *(.bss.$RamAHB16*)
. = ALIGN(4) ; . = ALIGN(4) ;
PROVIDE(__end_bss_RAM2 = .) ; PROVIDE(__end_bss_RAM2 = .) ;
} > RamAHB16 } > RamAHB16
/* MAIN BSS SECTION */ /* MAIN BSS SECTION */
...@@ -129,24 +127,24 @@ SECTIONS ...@@ -129,24 +127,24 @@ SECTIONS
_ebss = .; _ebss = .;
PROVIDE(end = .); PROVIDE(end = .);
} > RamLoc16 } > RamLoc16
/* NOINIT section for RamAHB16 */ /* NOINIT section for RamAHB16 */
.noinit_RAM2 (NOLOAD) : ALIGN(4) .noinit_RAM2 (NOLOAD) : ALIGN(4)
{ {
*(.noinit_RAM2*) *(.noinit_RAM2*)
*(.noinit_RamAHB16*) *(.noinit_RamAHB16*)
. = ALIGN(4) ; . = ALIGN(4) ;
} > RamAHB16 } > RamAHB16
/* DEFAULT NOINIT SECTION */ /* DEFAULT NOINIT SECTION */
.noinit (NOLOAD): ALIGN(4) .noinit (NOLOAD): ALIGN(4)
{ {
_noinit = .; _noinit = .;
*(.noinit*) *(.noinit*)
. = ALIGN(4) ; . = ALIGN(4) ;
_end_noinit = .; _end_noinit = .;
} > RamLoc16 } > RamLoc16
PROVIDE(_pvHeapStart = DEFINED(__user_heap_base) ? __user_heap_base : .); PROVIDE(_pvHeapStart = DEFINED(__user_heap_base) ? __user_heap_base : .);
PROVIDE(_vStackTop = DEFINED(__user_stack_top) ? __user_stack_top : __top_RamLoc16 - 0); PROVIDE(_vStackTop = DEFINED(__user_stack_top) ? __user_stack_top : __top_RamLoc16 - 0);
} }
/*
* GENERATED FILE - DO NOT EDIT
* (c) Code Red Technologies Ltd, 2008-2015
* (c) NXP Semiconductors 2013-2015
* Linker script memory definitions
* Created from LinkMemoryTemplate
* By LPCXpresso v7.8.0 [Build 426] [2015-05-28] on Thu Jul 30 09:03:05 BRT 2015)
*/
MEMORY
{
/* Define each memory region */
MFlash128 (rx) : ORIGIN = 0x0, LENGTH = 0x20000 /* 128K bytes */
RamLoc16 (rwx) : ORIGIN = 0x10000000, LENGTH = 0x4000 /* 16K bytes */
RamAHB16 (rwx) : ORIGIN = 0x2007c000, LENGTH = 0x4000 /* 16K bytes */
}
/* Define a symbol for the top of each memory region */
__top_MFlash128 = 0x0 + 0x20000;
__top_RamLoc16 = 0x10000000 + 0x4000;
__top_RamAHB16 = 0x2007c000 + 0x4000;
/* /*
* AFC_IPM.c * openMMC -- Open Source modular IPM Controller firmware
* *
* AFCIPMI -- * Copyright (C) 2015 Henrique Silva <henrique.silva@lnls.br>
* * Copyright (C) 2015 Piotr Miedzik <P.Miedzik@gsi.de>
* Copyright (C) 2015 Henrique Silva <henrique.silva@lnls.br>
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
...@@ -17,6 +16,8 @@ ...@@ -17,6 +16,8 @@
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* @license GPL-3.0+ <http://spdx.org/licenses/GPL-3.0+>
*/ */
/* Kernel includes. */ /* Kernel includes. */
...@@ -28,9 +29,7 @@ ...@@ -28,9 +29,7 @@
/* Project includes */ /* Project includes */
#include "chip.h" #include "chip.h"
#include "pin_mapping.h" #include "pin_mapping.h"
#include "i2c.h"
#include "led.h" #include "led.h"
#include "ipmb.h"
#include "ipmi.h" #include "ipmi.h"
#include "sdr.h" #include "sdr.h"
#include "payload.h" #include "payload.h"
...@@ -38,51 +37,62 @@ ...@@ -38,51 +37,62 @@
#include "fru.h" #include "fru.h"
#include "jtag.h" #include "jtag.h"
#include "fpga_spi.h" #include "fpga_spi.h"
#include "watchdog.h"
//#define HEAP_TEST //#define HEAP_TEST
//#define STOP_TEST
/* LED pins initialization */ /* LED pins initialization */
static void prvHardwareInit( void );
TickType_t getTickDifference(TickType_t current_time, TickType_t start_time);
void heap_test ( void* param); void heap_test ( void* param);
TaskHandle_t heap_handle; TaskHandle_t heap_handle;
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
uint8_t ipmb_addr = 0xFF;
int main(void) int main(void)
{ {
/* Update clock register value - LPC specific */ /* Update clock register value - LPC specific */
SystemCoreClockUpdate(); SystemCoreClockUpdate();
/* Configure LED pins */
prvHardwareInit();
#if (configGENERATE_RUN_TIME_STATS == 1) #if (configGENERATE_RUN_TIME_STATS == 1)
vConfigureTimerForRunTimeStats(); vConfigureTimerForRunTimeStats();
#endif #endif
//#define STOP_TEST
#ifdef STOP_TEST #ifdef STOP_TEST
int test = 0; int test = 0;
while (test == 0) while (test == 0)
{} {}
#endif #endif
#ifdef MODULE_WATCHDOG
watchdog_init();
#endif
LED_init(); LED_init();
#ifdef MODULE_FRU
fru_init(); fru_init();
portENABLE_INTERRUPTS(); #endif
afc_board_i2c_init(); portENABLE_INTERRUPTS();
afc_board_discover(); board_i2c_init();
board_discover();
portDISABLE_INTERRUPTS(); portDISABLE_INTERRUPTS();
ipmb_addr = get_ipmb_addr( ); ipmb_addr = get_ipmb_addr();
sdr_init(ipmb_addr); #ifdef MODULE_SDR
sdr_init();
#endif
#ifdef MODULE_SENSORS
sensor_init(); sensor_init();
#endif
#ifdef MODULE_PAYLOAD
payload_init(); payload_init();
do_quiesced_init(); #endif
#ifdef MODULE_JTAG_SWITCH
init_scansta(); init_scansta();
#endif
#ifdef MODULE_FPGA_SPI
init_fpga_spi(); init_fpga_spi();
#endif
/* Init IPMI interface */ /* Init IPMI interface */
/* NOTE: ipmb_init() is called inside this function */ /* NOTE: ipmb_init() is called inside this function */
ipmi_init(); ipmi_init();
...@@ -99,19 +109,13 @@ int main(void) ...@@ -99,19 +109,13 @@ int main(void)
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Put the MCU in sleep state when no task is running */
TickType_t getTickDifference(TickType_t current_time, TickType_t start_time) void vApplicationIdleHook (void) {
{ pm_sleep();
TickType_t result = 0;
if (current_time < start_time) {
result = start_time - current_time;
result = portMAX_DELAY - result;
} else {
result = current_time - start_time;
}
return result;
} }
/*-----------------------------------------------------------*/
/* System Debug funtions */
#ifdef HEAP_TEST #ifdef HEAP_TEST
static char stats[500]; static char stats[500];
void heap_test ( void* param) void heap_test ( void* param)
...@@ -121,58 +125,13 @@ void heap_test ( void* param) ...@@ -121,58 +125,13 @@ void heap_test ( void* param)
for (;;) { for (;;) {
ulTaskNotifyTake(pdTRUE, portMAX_DELAY); ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
water_mark = uxTaskGetStackHighWaterMark(NULL); water_mark = uxTaskGetStackHighWaterMark(NULL);
used_heap = configTOTAL_HEAP_SIZE - xPortGetFreeHeapSize(); used_heap = configTOTAL_HEAP_SIZE - xPortGetFreeHeapSize();
vTaskGetRunTimeStats(stats); vTaskGetRunTimeStats(stats);
} }
} }
#endif #endif
void prvToggleLED( LED_id led )
{
unsigned long ulLEDState;
unsigned long ulLEDport;
unsigned long ulLEDpin;
switch( led ){
case LED_BLUE:
ulLEDport = LEDBLUE_PORT;
ulLEDpin = LEDBLUE_PIN;
break;
case LED_GREEN:
ulLEDport = LEDGREEN_PORT;
ulLEDpin = LEDGREEN_PIN;
break;
case LED_RED:
ulLEDport = LEDRED_PORT;
ulLEDpin = LEDRED_PIN;
break;
default:
break;
}
/* Obtain the current P0 state. */
ulLEDState = Chip_GPIO_GetPinState(LPC_GPIO, ulLEDport, ulLEDpin);
/* Turn the LED off if it was on, and on if it was off. */
Chip_GPIO_SetPinState(LPC_GPIO, ulLEDport, ulLEDpin, !ulLEDState);
}
/*-----------------------------------------------------------*/
static void prvHardwareInit ( void )
{
/* Init LED Pin */
Chip_GPIO_Init(LPC_GPIO);
/* Set pin as output */
Chip_GPIO_SetPinDIR(LPC_GPIO, LEDBLUE_PORT, LEDBLUE_PIN, true);
Chip_GPIO_SetPinDIR(LPC_GPIO, LEDGREEN_PORT, LEDGREEN_PIN, true);
Chip_GPIO_SetPinDIR(LPC_GPIO, LEDRED_PORT, LEDRED_PIN, true);
/* Init GAddr test pin as output */
Chip_GPIO_SetPinDIR(LPC_GPIO, GA_TEST_PORT, GA_TEST_PIN, true);
}
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* FreeRTOS Debug Functions */ /* FreeRTOS Debug Functions */
...@@ -183,14 +142,12 @@ void vApplicationStackOverflowHook ( TaskHandle_t pxTask, signed char * pcTaskNa ...@@ -183,14 +142,12 @@ void vApplicationStackOverflowHook ( TaskHandle_t pxTask, signed char * pcTaskNa
taskDISABLE_INTERRUPTS(); taskDISABLE_INTERRUPTS();
/* Place a breakpoint here, so we know when there's a stack overflow */ /* Place a breakpoint here, so we know when there's a stack overflow */
for ( ; ; ) { for ( ; ; ) {
uint32_t watermark = uxTaskGetStackHighWaterMark(pxTask); uxTaskGetStackHighWaterMark(pxTask);
} }
} }
#endif #endif
#if (configGENERATE_RUN_TIME_STATS == 1) #if (configGENERATE_RUN_TIME_STATS == 1)
void vConfigureTimerForRunTimeStats( void ) void vConfigureTimerForRunTimeStats( void )
{ {
const unsigned long CTCR_CTM_TIMER = 0x00, TCR_COUNT_ENABLE = 0x01; const unsigned long CTCR_CTM_TIMER = 0x00, TCR_COUNT_ENABLE = 0x01;
...@@ -213,7 +170,6 @@ void vConfigureTimerForRunTimeStats( void ) ...@@ -213,7 +170,6 @@ void vConfigureTimerForRunTimeStats( void )
void vAssertCalled( char* file, uint32_t line) { void vAssertCalled( char* file, uint32_t line) {
taskDISABLE_INTERRUPTS(); taskDISABLE_INTERRUPTS();
prvToggleLED(LED_RED);
for( ;; ); for( ;; );
} }
...@@ -222,8 +178,3 @@ void vApplicationMallocFailedHook( void ) { ...@@ -222,8 +178,3 @@ void vApplicationMallocFailedHook( void ) {
} }
#endif #endif
void vApplicationIdleHook (void) {
}
set(MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR})
set(PROJ_HDRS ${PROJ_HDRS} ${MODULE_PATH} )
set(PROJ_SRCS ${PROJ_SRCS} ${MODULE_PATH}/utils.c)
set(PROJ_SRCS ${PROJ_SRCS} ${MODULE_PATH}/board_version.c)
set(PROJ_SRCS ${PROJ_SRCS} ${MODULE_PATH}/led.c)
set(PROJ_SRCS ${PROJ_SRCS} ${MODULE_PATH}/ipmb.c ${MODULE_PATH}/ipmi.c)
message(STATUS "Selected modules to compile: ${TARGET_MODULES}")
if (";${TARGET_MODULES};" MATCHES ";FRU;")
set(PROJ_SRCS ${PROJ_SRCS} ${MODULE_PATH}/fru.c )
set(MODULES_FLAGS "${MODULES_FLAGS} -DMODULE_FRU")
endif()
if (";${TARGET_MODULES};" MATCHES ";PAYLOAD;")
set(PROJ_SRCS ${PROJ_SRCS} ${MODULE_PATH}/payload.c)
set(MODULES_FLAGS "${MODULES_FLAGS} -DMODULE_PAYLOAD")
endif()
if (";${TARGET_MODULES};" MATCHES ";SDR;")
set(PROJ_SRCS ${PROJ_SRCS} ${MODULE_PATH}/sdr.c )
set(MODULES_FLAGS "${MODULES_FLAGS} -DMODULE_SDR")
endif()
if (";${TARGET_MODULES};" MATCHES ";WATCHDOG;")
set(PROJ_SRCS ${PROJ_SRCS} ${MODULE_PATH}/watchdog.c )
set(MODULES_FLAGS "${MODULES_FLAGS} -DMODULE_WATCHDOG")
endif()
if (";${TARGET_MODULES};" MATCHES ";HPM;")
set(PROJ_SRCS ${PROJ_SRCS} ${MODULE_PATH}/hpm.c )
set(MODULES_FLAGS "${MODULES_FLAGS} -DMODULE_HPM")
if (";${TARGET_MODULES};" MATCHES ";PAYLOAD;")
set(PROJ_SRCS ${PROJ_SRCS} ${MODULE_PATH}/flash_spi.c )
set(MODULES_FLAGS "${MODULES_FLAGS} -DMODULE_FLASH_SPI")
endif()
endif()
if (";${TARGET_MODULES};" MATCHES "SENSOR")
set(MODULES_FLAGS "${MODULES_FLAGS} -DMODULE_SENSORS")
add_subdirectory(sensors)
endif()
#Modules dependencies check
if(${TARGET_BOARD_NAME} MATCHES "^(AFC)")
if (("${MODULES_FLAGS}" MATCHES "-DMODULE_PAYLOAD") AND NOT ("${MODULES_FLAGS}" MATCHES "-DMODULE_DAC_AD84XX"))
message(WARNING "${Red}[AFC] Payload module is being used but the DAC_AD84XX was not included in this build. The VADJ reference will not be configured! ${ColourReset}")
endif()
endif()
if(NOT ("${MODULES_FLAGS}" MATCHES "-DMODULE_HOTSWAP"))
message(FATAL_ERROR "${Red}[ERROR] Mandatory Hotswap sensor module not included!${ColourReset}")
endif()
set(PROJ_SRCS ${PROJ_SRCS} PARENT_SCOPE)
set(PROJ_HDRS ${PROJ_HDRS} PARENT_SCOPE)
set(MODULES_FLAGS ${MODULES_FLAGS} PARENT_SCOPE)
/* /*
* board_version.c * openMMC -- Open Source modular IPM Controller firmware
* *
* AFCIPMI -- * Copyright (C) 2015 Piotr Miedzik <P.Miedzik@gsi.de>
* * Copyright (C) 2015-2016 Henrique Silva <henrique.silva@lnls.br>
* Copyright (C) 2015 Piotr Miedzik <P.Miedzik@gsi.de>
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
...@@ -17,15 +16,17 @@ ...@@ -17,15 +16,17 @@
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* @license GPL-3.0+ <http://spdx.org/licenses/GPL-3.0+>
*/ */
#include "FreeRTOS.h" #include "FreeRTOS.h"
#include "semphr.h" #include "semphr.h"
#include "utils.h"
#include "board_version.h" #include "board_version.h"
#include "port.h" #include "port.h"
#include "ipmb.h" #include "ipmb.h"
#include "i2c.h"
/* Chip_ID /* Chip_ID
* 0 <- LM75AIM * 0 <- LM75AIM
...@@ -41,7 +42,6 @@ struct i2c_chip_mapping { ...@@ -41,7 +42,6 @@ struct i2c_chip_mapping {
uint8_t chip_id; uint8_t chip_id;
uint8_t bus_id; uint8_t bus_id;
uint8_t i2c_address; uint8_t i2c_address;
uint8_t i2c_address2;
}; };
struct i2c_bus_mapping { struct i2c_bus_mapping {
...@@ -58,12 +58,11 @@ struct i2c_mux_state { ...@@ -58,12 +58,11 @@ struct i2c_mux_state {
I2C_ID_T i2c_interface; I2C_ID_T i2c_interface;
int8_t state; int8_t state;
SemaphoreHandle_t semaphore; SemaphoreHandle_t semaphore;
TickType_t start_time;
}; };
struct i2c_mux_state i2c_mux[] = { struct i2c_mux_state i2c_mux[] = {
{ I2C1, -1, 0, 0 }, { I2C1, -1, 0 },
{ I2C2, -1, 0, 0 }, { I2C2, -1, 0 },
}; };
#define I2C_MUX_COUNT (sizeof(i2c_mux) / sizeof(struct i2c_mux_state)) #define I2C_MUX_COUNT (sizeof(i2c_mux) / sizeof(struct i2c_mux_state))
...@@ -71,135 +70,154 @@ struct i2c_mux_state i2c_mux[] = { ...@@ -71,135 +70,154 @@ struct i2c_mux_state i2c_mux[] = {
struct i2c_bus_mapping *p_i2c_busmap = NULL; struct i2c_bus_mapping *p_i2c_busmap = NULL;
struct i2c_bus_mapping i2c_bus_map_afc_v2[] = { struct i2c_bus_mapping i2c_bus_map_afc_v2[] = {
{ I2C_BUS_UNKNOWN_ID, I2C1, -1, 0 }, { I2C_BUS_UNKNOWN_ID, I2C1, -1, 0 },
{ I2C_BUS_FMC1_ID, I2C1, 0, 1 }, { I2C_BUS_FMC1_ID, I2C1, 0, 1 },
{ I2C_BUS_FMC2_ID, I2C2, -1, 1 }, { I2C_BUS_FMC2_ID, I2C2, -1, 1 },
{ I2C_BUS_CPU_ID, I2C1, 1, 1 }, { I2C_BUS_CPU_ID, I2C1, 1, 1 },
{ I2C_BUS_RTM_ID, I2C1, 0, 0 }, { I2C_BUS_RTM_ID, I2C1, 0, 0 },
{ I2C_BUS_CLOCK_ID, I2C1, 0, 1 }, { I2C_BUS_CLOCK_ID, I2C1, 0, 1 },
{ I2C_BUS_FPGA_ID, I2C1, 0, 0 }, { I2C_BUS_FPGA_ID, I2C1, 0, 0 },
}; };
struct i2c_bus_mapping i2c_bus_map_afc_v3[] = { struct i2c_bus_mapping i2c_bus_map_afc_v3[] = {
{ I2C_BUS_UNKNOWN_ID, I2C1, -1, 0 }, { I2C_BUS_UNKNOWN_ID, I2C1, -1, 0 },
{ I2C_BUS_FMC1_ID, I2C1, 0, 1 }, { I2C_BUS_FMC1_ID, I2C1, 0, 1 },
{ I2C_BUS_FMC2_ID, I2C1, 1, 1 }, { I2C_BUS_FMC2_ID, I2C1, 1, 1 },
{ I2C_BUS_CPU_ID, I2C1, -1, 1 }, { I2C_BUS_CPU_ID, I2C1, -1, 1 },
{ I2C_BUS_RTM_ID, I2C1, 3, 1 }, { I2C_BUS_RTM_ID, I2C1, 3, 1 },
{ I2C_BUS_CLOCK_ID, I2C1, 2, 1 }, { I2C_BUS_CLOCK_ID, I2C1, 2, 1 },
{ I2C_BUS_FPGA_ID, I2C1, 0, 0 }, { I2C_BUS_FPGA_ID, I2C1, 0, 0 },
}; };
struct i2c_bus_mapping i2c_bus_map_afc_v3_1[] = { struct i2c_bus_mapping i2c_bus_map_afc_v3_1[] = {
{ I2C_BUS_UNKNOWN_ID, I2C1, -1, 0 }, { I2C_BUS_UNKNOWN_ID, I2C1, -1, 0 },
{ I2C_BUS_FMC1_ID, I2C2, 1, 1 }, { I2C_BUS_FMC1_ID, I2C2, 0, 1 },
{ I2C_BUS_FMC2_ID, I2C2, 0, 1 }, { I2C_BUS_FMC2_ID, I2C2, 1, 1 },
{ I2C_BUS_CPU_ID, I2C1, -1, 1 }, { I2C_BUS_CPU_ID, I2C1, -1, 1 },
{ I2C_BUS_RTM_ID, I2C2, 3, 1 }, { I2C_BUS_RTM_ID, I2C2, 3, 1 },
{ I2C_BUS_CLOCK_ID, I2C2, 2, 1 }, { I2C_BUS_CLOCK_ID, I2C2, 2, 1 },
{ I2C_BUS_FPGA_ID, I2C2, -1, 1 }, { I2C_BUS_FPGA_ID, I2C2, -1, 1 },
}; };
struct i2c_chip_mapping i2c_chip_map[] = { struct i2c_chip_mapping i2c_chip_map[] = {
{CHIP_ID_MUX , I2C_BUS_CPU_ID, 0x70}, { CHIP_ID_MUX, I2C_BUS_CPU_ID, 0x70},
{CHIP_ID_LM75AIM_0, I2C_BUS_CPU_ID, 0x4C}, { CHIP_ID_LM75AIM_0, I2C_BUS_CPU_ID, 0x4C},
{CHIP_ID_LM75AIM_1, I2C_BUS_CPU_ID, 0x4D}, { CHIP_ID_LM75AIM_1, I2C_BUS_CPU_ID, 0x4D},
{CHIP_ID_LM75AIM_2, I2C_BUS_CPU_ID, 0x4E}, { CHIP_ID_LM75AIM_2, I2C_BUS_CPU_ID, 0x4E},
{CHIP_ID_LM75AIM_3, I2C_BUS_CPU_ID, 0x4F}, { CHIP_ID_LM75AIM_3, I2C_BUS_CPU_ID, 0x4F},
{CHIP_ID_MAX6642, I2C_BUS_CPU_ID, 0x48}, { CHIP_ID_MAX6642, I2C_BUS_CPU_ID, 0x48},
{CHIP_ID_RTC, I2C_BUS_CPU_ID, 0x9F}, { CHIP_ID_RTC, I2C_BUS_CPU_ID, 0x9F},
{CHIP_ID_RTC_EEPROM, I2C_BUS_CPU_ID, 0x57}, { CHIP_ID_RTC_EEPROM, I2C_BUS_CPU_ID, 0x57},
{CHIP_ID_EEPROM, I2C_BUS_CPU_ID, 0x50}, { CHIP_ID_EEPROM, I2C_BUS_CPU_ID, 0x50},
{CHIP_ID_EEPROM_ID, I2C_BUS_CPU_ID, 0x58}, { CHIP_ID_EEPROM_ID, I2C_BUS_CPU_ID, 0x58},
{CHIP_ID_INA_0, I2C_BUS_CPU_ID, 0x40}, { CHIP_ID_INA_0, I2C_BUS_CPU_ID, 0x40},
{CHIP_ID_INA_1, I2C_BUS_CPU_ID, 0x41}, { CHIP_ID_INA_1, I2C_BUS_CPU_ID, 0x41},
{CHIP_ID_INA_2, I2C_BUS_CPU_ID, 0x42}, { CHIP_ID_INA_2, I2C_BUS_CPU_ID, 0x42},
{CHIP_ID_INA_3, I2C_BUS_CPU_ID, 0x43}, { CHIP_ID_INA_3, I2C_BUS_CPU_ID, 0x43},
{CHIP_ID_INA_4, I2C_BUS_CPU_ID, 0x44}, { CHIP_ID_INA_4, I2C_BUS_CPU_ID, 0x44},
{CHIP_ID_INA_5, I2C_BUS_CPU_ID, 0x45}, { CHIP_ID_INA_5, I2C_BUS_CPU_ID, 0x45},
{CHIP_ID_ADN, I2C_BUS_CLOCK_ID, 0x4B}, { CHIP_ID_ADN, I2C_BUS_CLOCK_ID, 0x4B},
{CHIP_ID_SI57x, I2C_BUS_CLOCK_ID, 0x30}, { CHIP_ID_SI57x, I2C_BUS_CLOCK_ID, 0x30},
{CHIP_ID_EEPROM_FMC1, I2C_BUS_FMC1_ID, 0x4B}, { CHIP_ID_FMC1_EEPROM, I2C_BUS_FMC1_ID, 0x50},
{CHIP_ID_EEPROM_FMC2, I2C_BUS_FMC2_ID, 0x30}, { CHIP_ID_FMC1_LM75_0, I2C_BUS_FMC1_ID, 0x48},
{ CHIP_ID_FMC1_LM75_1, I2C_BUS_FMC1_ID, 0x49},
{ CHIP_ID_FMC2_EEPROM, I2C_BUS_FMC2_ID, 0x52},
{ CHIP_ID_FMC2_LM75_0, I2C_BUS_FMC2_ID, 0x48},
{ CHIP_ID_FMC2_LM75_1, I2C_BUS_FMC2_ID, 0x49},
}; };
#define I2C_CHIP_MAP_COUNT (sizeof(i2c_chip_map)/sizeof(struct i2c_chip_mapping)) #define I2C_CHIP_MAP_COUNT (sizeof(i2c_chip_map)/sizeof(struct i2c_chip_mapping))
void afc_board_i2c_init( void ) manufacturing_info_raw board_info = {0};
void board_i2c_init( void )
{ {
int i; uint8_t i;
for (i=0; i<I2C_MUX_COUNT; i++) { for (i=0; i<I2C_MUX_COUNT; i++) {
i2c_mux[i].semaphore = xSemaphoreCreateBinary(); i2c_mux[i].semaphore = xSemaphoreCreateBinary();
vI2CInit(i2c_mux[i].i2c_interface, SPEED_100KHZ, I2C_Mode_Local_Master); vI2CConfig(i2c_mux[i].i2c_interface, SPEED_100KHZ);
xSemaphoreGive(i2c_mux[i].semaphore); xSemaphoreGive(i2c_mux[i].semaphore);
} }
} }
void afc_board_discover( void ) void board_discover( void )
{ {
portENABLE_INTERRUPTS(); portENABLE_INTERRUPTS();
//#define WRITE_EEPROM /* Check RTC EEPROM for board info */
#ifdef WRITE_EEPROM
#ifdef WRITE_ID_EEPROM
uint8_t unlock[2] = { 0x09, 0x00 }; uint8_t unlock[2] = { 0x09, 0x00 };
/* Carrier type (1-byte): uint8_t ee_write[9] = {
* 01h: artix based (AFC) /* Reserved (EEPROM starting Address */
* 02h: kintex based (AFCK) 0xF0,
* ....
Board version (1-byte): /* Carrier type (1-byte):
* 00h: AFCv1 * 01h: artix based (AFC)
* 01h: AFCv2 * 02h: kintex based (AFCK)
* 02h: AFCv3 * .... */
* 03h: AFCv3.1 0x01,
Manufacturer Private Enterprise Numbers assigned by IANA (3-bytes big-endian) /* Board version (1-byte):
* 00h 9Ah 65h (39525): Creotech * 00h: AFCv1
* ..... * 01h: AFCv2
* 02h: AFCv3
* 03h: AFCv3.1 */
0x03,
Manufacturing day since 1996-01-01 (2-bytes big-endian) /* Manufacturer Private Enterprise Numbers assigned by IANA (3-bytes big-endian)
* 1Bh 1Ch (6940) : 2015-01-01 * 00h 9Ah 65h (39525): Creotech
* ..... */
0x00, 0x9A, 0x65,
Checksum (1-byte) */ /* Manufacturing day since 1996-01-01 (2-bytes big-endian)
* 1Bh 1Ch (6940) : 2015-01-01 */
0x1B, 0x1C,
uint8_t ee_write[9] = { 0xF0, 0x01, 0x03, 0x00, 0x9A, 0x65, 0x1B, 0x1C, 0x00 }; /* Checksum (1-byte) */
ee_write[8] = ipmb_calculate_chksum(&ee_write[1], 8); 0x00 };
/* Calculate checksum */
ee_write[8] = calculate_chksum(&ee_write[1], 8);
/* Unlock protected EEPROM */ /* Unlock protected EEPROM */
unlock[1] = 0x55; unlock[1] = 0x55;
xI2CMasterWrite(I2C1, 0x6F, unlock, 2); xI2CMasterWrite(I2C1, 0x6F, unlock, 2);
unlock[1] = 0xAA; unlock[1] = 0xAA;
xI2CMasterWrite(I2C1, 0x6F, unlock, 2); xI2CMasterWrite(I2C1, 0x6F, unlock, 2);
/* Write data */ /* Write data */
xI2CMasterWrite(I2C1, 0x57, ee_write, sizeof(ee_write)); xI2CMasterWrite(I2C1, 0x57, ee_write, sizeof(ee_write));
#endif #endif
if (xI2CMasterWriteRead(I2C1, 0x57, 0xF0, (uint8_t *) &afc_board_info, sizeof(afc_board_info) ) != sizeof(afc_board_info) ) { if (xI2CMasterWriteRead(I2C1, 0x57, 0xF0, (uint8_t *) &board_info, sizeof(board_info) ) != sizeof(board_info) ) {
return; return;
} }
portDISABLE_INTERRUPTS(); uint8_t crc_fail = calculate_chksum((uint8_t *) &board_info, 8 );
uint8_t crc_fail = ipmb_calculate_chksum((uint8_t *) &afc_board_info, 8 ); portDISABLE_INTERRUPTS();
if (crc_fail == 0) { if (crc_fail == 0) {
if ( ( afc_board_info.carrier_type == CARRIER_TYPE_AFC && afc_board_info.board_version == 0x00 ) || if ( ( board_info.carrier_type == CARRIER_TYPE_AFC && board_info.board_version == 0x00 ) ||
( afc_board_info.carrier_type == CARRIER_TYPE_AFC && afc_board_info.board_version == 0x01 ) ) { ( board_info.carrier_type == CARRIER_TYPE_AFC && board_info.board_version == 0x01 ) ) {
p_i2c_busmap = i2c_bus_map_afc_v2;
i2c_chip_map[CHIP_ID_MUX].bus_id = I2C_BUS_UNKNOWN_ID; i2c_chip_map[CHIP_ID_MUX].bus_id = I2C_BUS_UNKNOWN_ID;
i2c_chip_map[CHIP_ID_MUX].i2c_address = 0x00; i2c_chip_map[CHIP_ID_MUX].i2c_address = 0x00;
p_i2c_busmap = i2c_bus_map_afc_v2;
} else if ((afc_board_info.carrier_type == CARRIER_TYPE_AFC && afc_board_info.board_version == 0x02) || } else if ((board_info.carrier_type == CARRIER_TYPE_AFC && board_info.board_version == 0x02) ||
afc_board_info.carrier_type == CARRIER_TYPE_AFCK) { board_info.carrier_type == CARRIER_TYPE_AFCK) {
p_i2c_busmap = i2c_bus_map_afc_v3; p_i2c_busmap = i2c_bus_map_afc_v3;
i2c_chip_map[CHIP_ID_MUX].bus_id = I2C_BUS_CPU_ID; i2c_chip_map[CHIP_ID_MUX].bus_id = I2C_BUS_CPU_ID;
i2c_chip_map[CHIP_ID_MUX].i2c_address = 0x70; i2c_chip_map[CHIP_ID_MUX].i2c_address = 0x70;
} else if ((afc_board_info.carrier_type == CARRIER_TYPE_AFC && afc_board_info.board_version == 0x03)) {
} else if ((board_info.carrier_type == CARRIER_TYPE_AFC && board_info.board_version == 0x03)) {
p_i2c_busmap = i2c_bus_map_afc_v3_1; p_i2c_busmap = i2c_bus_map_afc_v3_1;
i2c_chip_map[CHIP_ID_MUX].bus_id = I2C_BUS_FPGA_ID; i2c_chip_map[CHIP_ID_MUX].bus_id = I2C_BUS_FPGA_ID;
i2c_chip_map[CHIP_ID_MUX].i2c_address = 0x70; i2c_chip_map[CHIP_ID_MUX].i2c_address = 0x70;
...@@ -210,24 +228,25 @@ void afc_board_discover( void ) ...@@ -210,24 +228,25 @@ void afc_board_discover( void )
} }
} }
void afc_get_manufacturing_info( manufacturing_info_raw *p_board_info ) void get_manufacturing_info( manufacturing_info_raw *p_board_info )
{ {
if (p_board_info != NULL) {
p_board_info = &board_info;
}
} }
void afc_get_board_type(uint8_t *carrier_type, uint8_t *board_version) void get_board_type(uint8_t *carrier_type, uint8_t *board_version)
{ {
if (carrier_type != NULL) { if (carrier_type != NULL) {
*carrier_type = afc_board_info.carrier_type; *carrier_type = board_info.carrier_type;
} }
if (board_version != NULL) { if (board_version != NULL) {
*board_version = afc_board_info.board_version; *board_version = board_info.board_version;
} }
} }
Bool i2c_take_by_busid( uint8_t bus_id, I2C_ID_T * i2c_interface, TickType_t max_wait_time )
Bool afc_i2c_take_by_busid( uint8_t bus_id, I2C_ID_T * i2c_interface, TickType_t max_wait_time )
{ {
uint8_t i; uint8_t i;
struct i2c_mux_state * p_i2c_mux = NULL; struct i2c_mux_state * p_i2c_mux = NULL;
...@@ -267,7 +286,8 @@ Bool afc_i2c_take_by_busid( uint8_t bus_id, I2C_ID_T * i2c_interface, TickType_t ...@@ -267,7 +286,8 @@ Bool afc_i2c_take_by_busid( uint8_t bus_id, I2C_ID_T * i2c_interface, TickType_t
*i2c_interface = p_i2c_mux->i2c_interface; *i2c_interface = p_i2c_mux->i2c_interface;
return true; return true;
} else if (i2c_chip_map[CHIP_ID_MUX].bus_id == I2C_BUS_UNKNOWN_ID) { } else if (i2c_chip_map[CHIP_ID_MUX].bus_id == I2C_BUS_UNKNOWN_ID) {
/* Change bus mux */ /* Change bus mux inside LPC1764
* (There's two set of pins that can operate as I2C1) */
if (p_i2c_bus->mux_bus == 0) { if (p_i2c_bus->mux_bus == 0) {
/*! @todo Change LPC specific functions for generic macros */ /*! @todo Change LPC specific functions for generic macros */
Chip_I2C_Disable(p_i2c_bus->i2c_interface); Chip_I2C_Disable(p_i2c_bus->i2c_interface);
...@@ -275,17 +295,15 @@ Bool afc_i2c_take_by_busid( uint8_t bus_id, I2C_ID_T * i2c_interface, TickType_t ...@@ -275,17 +295,15 @@ Bool afc_i2c_take_by_busid( uint8_t bus_id, I2C_ID_T * i2c_interface, TickType_t
Chip_IOCON_PinMux(LPC_IOCON, 0, 0, IOCON_MODE_INACT, IOCON_FUNC0); Chip_IOCON_PinMux(LPC_IOCON, 0, 0, IOCON_MODE_INACT, IOCON_FUNC0);
Chip_IOCON_PinMux(LPC_IOCON, 0, 1, IOCON_MODE_INACT, IOCON_FUNC0); Chip_IOCON_PinMux(LPC_IOCON, 0, 1, IOCON_MODE_INACT, IOCON_FUNC0);
//Chip_IOCON_EnableOD(LPC_IOCON, 0, 0);
//Chip_IOCON_EnableOD(LPC_IOCON, 0, 1);
Chip_IOCON_PinMux(LPC_IOCON, 0, 19, IOCON_MODE_INACT, IOCON_FUNC3); Chip_IOCON_PinMux(LPC_IOCON, 0, 19, IOCON_MODE_INACT, IOCON_FUNC3);
Chip_IOCON_PinMux(LPC_IOCON, 0, 20, IOCON_MODE_INACT, IOCON_FUNC3); Chip_IOCON_PinMux(LPC_IOCON, 0, 20, IOCON_MODE_INACT, IOCON_FUNC3);
Chip_IOCON_EnableOD(LPC_IOCON, 0, 19); Chip_IOCON_EnableOD(LPC_IOCON, 0, 19);
Chip_IOCON_EnableOD(LPC_IOCON, 0, 20); Chip_IOCON_EnableOD(LPC_IOCON, 0, 20);
Chip_I2C_Init(p_i2c_bus->i2c_interface); Chip_I2C_Init(p_i2c_bus->i2c_interface);
Chip_I2C_Enable(p_i2c_bus->i2c_interface); Chip_I2C_Enable(p_i2c_bus->i2c_interface);
} else if ((p_i2c_bus->mux_bus == 1)) { } else if (p_i2c_bus->mux_bus == 1) {
Chip_I2C_Disable(p_i2c_bus->i2c_interface); Chip_I2C_Disable(p_i2c_bus->i2c_interface);
Chip_I2C_DeInit(p_i2c_bus->i2c_interface); Chip_I2C_DeInit(p_i2c_bus->i2c_interface);
...@@ -308,10 +326,13 @@ Bool afc_i2c_take_by_busid( uint8_t bus_id, I2C_ID_T * i2c_interface, TickType_t ...@@ -308,10 +326,13 @@ Bool afc_i2c_take_by_busid( uint8_t bus_id, I2C_ID_T * i2c_interface, TickType_t
p_i2c_mux->state = p_i2c_bus->mux_bus; p_i2c_mux->state = p_i2c_bus->mux_bus;
*i2c_interface = p_i2c_mux->i2c_interface; *i2c_interface = p_i2c_mux->i2c_interface;
return true; return true;
// this is mux inside MMC
} else { } else {
/* What'll happen if p_i2c_bus->mux_bus is '-1' ? I'm casting it as unsigned to prevent GCC pointer sign warning */ /* Include enable bit (fourth bit) on channel selection byte */
while (xI2CMasterWrite(i2c_chip_map[CHIP_ID_MUX].bus_id, i2c_chip_map[CHIP_ID_MUX].i2c_address, (uint8_t *)&p_i2c_bus->mux_bus, 1 ) < 1) { } uint8_t pca_channel = p_i2c_bus->mux_bus | (1 << 4);
while (xI2CMasterWrite(i2c_chip_map[CHIP_ID_MUX].bus_id, i2c_chip_map[CHIP_ID_MUX].i2c_address, &pca_channel, 1 ) == 0) { }
p_i2c_mux->state = p_i2c_bus->mux_bus; p_i2c_mux->state = p_i2c_bus->mux_bus;
*i2c_interface = p_i2c_mux->i2c_interface; *i2c_interface = p_i2c_mux->i2c_interface;
return true; return true;
...@@ -321,7 +342,7 @@ Bool afc_i2c_take_by_busid( uint8_t bus_id, I2C_ID_T * i2c_interface, TickType_t ...@@ -321,7 +342,7 @@ Bool afc_i2c_take_by_busid( uint8_t bus_id, I2C_ID_T * i2c_interface, TickType_t
return false; return false;
} }
Bool afc_i2c_take_by_chipid(uint8_t chip_id, uint8_t * i2c_address, I2C_ID_T * i2c_interface, TickType_t max_wait_time) Bool i2c_take_by_chipid(uint8_t chip_id, uint8_t * i2c_address, I2C_ID_T * i2c_interface, TickType_t max_wait_time)
{ {
if (chip_id > I2C_CHIP_MAP_COUNT) { if (chip_id > I2C_CHIP_MAP_COUNT) {
return false; return false;
...@@ -332,10 +353,10 @@ Bool afc_i2c_take_by_chipid(uint8_t chip_id, uint8_t * i2c_address, I2C_ID_T * i ...@@ -332,10 +353,10 @@ Bool afc_i2c_take_by_chipid(uint8_t chip_id, uint8_t * i2c_address, I2C_ID_T * i
*i2c_address = i2c_chip_map[chip_id].i2c_address; *i2c_address = i2c_chip_map[chip_id].i2c_address;
} }
return afc_i2c_take_by_busid(bus_id, i2c_interface, max_wait_time); return i2c_take_by_busid(bus_id, i2c_interface, max_wait_time);
} }
void afc_i2c_give(I2C_ID_T i2c_interface) void i2c_give(I2C_ID_T i2c_interface)
{ {
for (uint8_t i=0; i<I2C_MUX_COUNT; i++) { for (uint8_t i=0; i<I2C_MUX_COUNT; i++) {
if (i2c_mux[i].i2c_interface == i2c_interface) { if (i2c_mux[i].i2c_interface == i2c_interface) {
......
/* /*
* board_version.h * openMMC -- Open Source modular IPM Controller firmware
* *
* AFCIPMI -- * Copyright (C) 2015 Piotr Miedzik <P.Miedzik@gsi.de>
* * Copyright (C) 2015-2016 Henrique Silva <henrique.silva@lnls.br>
* Copyright (C) 2015 Piotr Miedzik <P.Miedzik@gsi.de>
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
...@@ -17,6 +16,8 @@ ...@@ -17,6 +16,8 @@
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* @license GPL-3.0+ <http://spdx.org/licenses/GPL-3.0+>
*/ */
#ifndef AFC_BOARD_VERSION_H_ #ifndef AFC_BOARD_VERSION_H_
...@@ -27,20 +28,19 @@ ...@@ -27,20 +28,19 @@
#include "semphr.h" #include "semphr.h"
#include "port.h" #include "port.h"
#define CARRIER_TYPE_UNKNOWN 0xFF #define CARRIER_TYPE_UNKNOWN 0xFF
#define CARRIER_TYPE_AFC 0x01 #define CARRIER_TYPE_AFC 0x01
#define CARRIER_TYPE_AFCK 0x02 #define CARRIER_TYPE_AFCK 0x02
#define BOARD_VERSION_AFC_V1_0 0x00 #define BOARD_VERSION_AFC_V1_0 0x00
#define BOARD_VERSION_AFC_V2_0 0x01 #define BOARD_VERSION_AFC_V2_0 0x01
#define BOARD_VERSION_AFC_V3_0 0x02 #define BOARD_VERSION_AFC_V3_0 0x02
#define BOARD_VERSION_AFC_V3_1 0x03 #define BOARD_VERSION_AFC_V3_1 0x03
#define BOARD_VERSION_UNKNOWN 0xFF #define BOARD_VERSION_UNKNOWN 0xFF
#define I2CMODE_POOLING 1
#define I2CMODE_POOLING 1 #define I2CMODE_INTERRUPT 0
#define I2CMODE_INTERRUPT 0 #define SPEED_100KHZ 100000
#define SPEED_100KHZ 100000
// BUS_ID // BUS_ID
// 0 - FMC1 // 0 - FMC1
...@@ -48,52 +48,57 @@ ...@@ -48,52 +48,57 @@
// 3 - CPU_ID // 3 - CPU_ID
// //
/////////////////////// ///////////////////////
#define I2C_BUS_UNKNOWN_ID 0
#define I2C_BUS_FMC1_ID 1
#define I2C_BUS_FMC2_ID 2
#define I2C_BUS_CPU_ID 3
#define I2C_BUS_RTM_ID 4
#define I2C_BUS_CLOCK_ID 5
#define I2C_BUS_FPGA_ID 6
#define CHIP_ID_MUX 0
#define CHIP_ID_LM75AIM_0 1
#define CHIP_ID_LM75AIM_1 2
#define CHIP_ID_LM75AIM_2 3
#define CHIP_ID_LM75AIM_3 4
#define CHIP_ID_MAX6642 5
#define CHIP_ID_RTC 6
#define CHIP_ID_RTC_EEPROM 7
#define CHIP_ID_EEPROM 8
#define CHIP_ID_EEPROM_ID 9
#define CHIP_ID_INA_0 10
#define CHIP_ID_INA_1 11
#define CHIP_ID_INA_2 12
#define CHIP_ID_INA_3 13
#define CHIP_ID_INA_4 14
#define CHIP_ID_INA_5 15
#define CHIP_ID_ADN 16
#define CHIP_ID_SI57x 17
#define CHIP_ID_EEPROM_FMC1 18 enum {
#define CHIP_ID_EEPROM_FMC2 19 I2C_BUS_UNKNOWN_ID = 0x00,
I2C_BUS_FMC1_ID,
I2C_BUS_FMC2_ID,
I2C_BUS_CPU_ID,
I2C_BUS_RTM_ID,
I2C_BUS_CLOCK_ID,
I2C_BUS_FPGA_ID
};
enum {
CHIP_ID_MUX = 0,
CHIP_ID_LM75AIM_0,
CHIP_ID_LM75AIM_1,
CHIP_ID_LM75AIM_2,
CHIP_ID_LM75AIM_3,
CHIP_ID_MAX6642,
CHIP_ID_RTC,
CHIP_ID_RTC_EEPROM,
CHIP_ID_EEPROM,
CHIP_ID_EEPROM_ID,
CHIP_ID_INA_0,
CHIP_ID_INA_1,
CHIP_ID_INA_2,
CHIP_ID_INA_3,
CHIP_ID_INA_4,
CHIP_ID_INA_5,
CHIP_ID_ADN,
CHIP_ID_SI57x,
CHIP_ID_FMC1_EEPROM,
CHIP_ID_FMC1_LM75_1,
CHIP_ID_FMC1_LM75_0,
CHIP_ID_FMC2_EEPROM,
CHIP_ID_FMC2_LM75_1,
CHIP_ID_FMC2_LM75_0
};
typedef struct { typedef struct {
uint8_t carrier_type; uint8_t carrier_type;
uint8_t board_version; uint8_t board_version;
uint8_t manufacturer[3]; uint8_t manufacturer[3];
uint8_t manufacturing_day[2]; uint8_t manufacturing_day[2];
uint8_t crc; uint8_t crc;
} manufacturing_info_raw; } manufacturing_info_raw;
typedef struct { typedef struct {
uint8_t carrier_version; uint8_t carrier_version;
uint8_t board_version; uint8_t board_version;
uint32_t manufacturer; uint32_t manufacturer;
uint16_t manufacturing_day; uint16_t manufacturing_day;
} manufacturing_info; } manufacturing_info;
typedef struct { typedef struct {
...@@ -102,14 +107,14 @@ typedef struct { ...@@ -102,14 +107,14 @@ typedef struct {
I2C_ID_T i2c_bus; I2C_ID_T i2c_bus;
} I2C_Mutex; } I2C_Mutex;
static manufacturing_info_raw afc_board_info; extern manufacturing_info_raw board_info;
void afc_board_i2c_init( void ); void board_i2c_init( void );
void afc_board_discover( void ); void board_discover( void );
void afc_get_manufacturing_info( manufacturing_info_raw *p_board_info ); void get_manufacturing_info( manufacturing_info_raw *p_board_info );
void afc_get_board_type( uint8_t *carrier_type, uint8_t *board_version); void get_board_type( uint8_t *carrier_type, uint8_t *board_version);
Bool afc_i2c_take_by_busid( uint8_t bus_id, I2C_ID_T * i2c_interface, TickType_t max_wait_time ); Bool i2c_take_by_busid( uint8_t bus_id, I2C_ID_T * i2c_interface, TickType_t max_wait_time );
Bool afc_i2c_take_by_chipid( uint8_t chip_id, uint8_t * i2c_address, I2C_ID_T * i2c_interface, TickType_t max_wait_time ); Bool i2c_take_by_chipid( uint8_t chip_id, uint8_t * i2c_address, I2C_ID_T * i2c_interface, TickType_t max_wait_time );
void afc_i2c_give( I2C_ID_T i2c_interface ); void i2c_give( I2C_ID_T i2c_interface );
#endif /* AFC_BOARD_VERSION_H_ */ #endif /* AFC_BOARD_VERSION_H_ */
/*
* openMMC -- Open Source modular IPM Controller firmware
*
* Copyright (C) 2015-2016 Henrique Silva <henrique.silva@lnls.br>
*
* 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 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* @license GPL-3.0+ <http://spdx.org/licenses/GPL-3.0+>
*/
/* FreeRTOS Includes */
#include "FreeRTOS.h"
/* Project Includes */
#include "port.h"
#include "flash_spi.h"
#include "pin_mapping.h"
#include <string.h>
void flash_write_enable( void )
{
do {
uint8_t tx_buff[1] = {FLASH_WRITE_ENABLE};
ssp_write( FLASH_SPI, tx_buff, sizeof(tx_buff) );
} while (!(flash_read_status_reg() & 0x2));
}
void flash_write_disable( void )
{
do {
uint8_t tx_buff[1] = {FLASH_WRITE_DISABLE};
ssp_write( FLASH_SPI, tx_buff, sizeof(tx_buff) );
} while (flash_read_status_reg() & 0x2);
}
void flash_read_id( uint8_t * id_buffer, uint8_t buff_size )
{
if ((buff_size < 3)|(id_buffer == NULL)) {
return;
}
uint8_t tx_buff[1] = {FLASH_READ_ID};
/* Size of rx buffer must be the sum of the length of the data expected to receive and the length of the sent data */
uint8_t rx_buff[4] = {0};
ssp_write_read( FLASH_SPI, &tx_buff[0], 1, &rx_buff[0], 3, portMAX_DELAY );
memcpy(id_buffer, &rx_buff[1], 3);
}
uint8_t flash_read_status_reg( void )
{
uint8_t tx_buff[1] = {FLASH_READ_STATUS_REG};
/* Size of rx buffer must be the sum of the length of the data expected to receive and the length of the sent data */
uint8_t rx_buff[2] = {0};
ssp_write_read( FLASH_SPI, &tx_buff[0], 1, &rx_buff[0], 1, portMAX_DELAY );
return rx_buff[1];
}
void flash_write_status_reg( uint8_t data )
{
uint8_t tx_buff[2] = {FLASH_WRITE_STATUS_REG, data};
flash_write_enable();
ssp_write( FLASH_SPI, &tx_buff[0], sizeof(tx_buff) );
}
uint8_t flash_read_lock_reg( uint32_t address )
{
uint8_t tx_buff[4];
tx_buff[0] = FLASH_READ_LOCK_REG;
tx_buff[1] = (address >> 16) & 0xFF;
tx_buff[2] = (address >> 8) & 0xFF;
tx_buff[3] = address & 0xFF;
/* Size of rx buffer must be the sum of the length of the data expected to receive and the length of the sent data */
uint8_t rx_buff[5] = {0};
ssp_write_read( FLASH_SPI, &tx_buff[0], sizeof(tx_buff), &rx_buff[0], sizeof(rx_buff), portMAX_DELAY );
return rx_buff[4];
}
void flash_write_lock_reg( uint32_t address, uint8_t data )
{
uint8_t tx_buff[5];
tx_buff[0] = FLASH_WRITE_LOCK_REG;
tx_buff[1] = (address >> 16) & 0xFF;
tx_buff[2] = (address >> 8) & 0xFF;
tx_buff[3] = address & 0xFF;
tx_buff[4] = data;
flash_write_enable();
ssp_write( FLASH_SPI, &tx_buff[0], sizeof(tx_buff) );
}
uint8_t flash_read_data( uint32_t address )
{
uint8_t tx_buff[4];
tx_buff[0] = FLASH_READ_DATA;
tx_buff[1] = (address >> 16) & 0xFF;
tx_buff[2] = (address >> 8) & 0xFF;
tx_buff[3] = address & 0xFF;
/* Size of rx buffer must be the sum of the length of the data expected to receive and the length of the sent data */
uint8_t rx_buff[5] = {0};
ssp_write_read( FLASH_SPI, &tx_buff[0], 4, &rx_buff[0], 1, portMAX_DELAY );
return rx_buff[4];
}
void flash_fast_read_data( uint32_t start_addr, uint8_t * dst, uint32_t size )
{
/* Size of rx buffer must be the sum of the length of the data expected to receive and the length of the sent data */
/* Use an additional Dumb byte */
uint8_t *rx_buff = pvPortMalloc(size+5);
uint8_t tx_buff[5];
tx_buff[0] = FLASH_FAST_READ_DATA;
tx_buff[1] = (start_addr >> 16) & 0xFF;
tx_buff[2] = (start_addr >> 8) & 0xFF;
tx_buff[3] = start_addr & 0xFF;
tx_buff[4] = 0xFF; /* Dumb Byte */
ssp_write_read( FLASH_SPI, &tx_buff[0], 5, &rx_buff[0], size, portMAX_DELAY );
memcpy(dst, &rx_buff[5], size);
vPortFree(rx_buff);
}
void flash_program_page( uint32_t address, uint8_t * data, uint16_t size )
{
/* The sector MUST be erased before trying to program new data into it */
flash_write_enable();
/* Use malloc to reserve 'size' plus 4 bytes (address and cmd) */
uint8_t *tx_buff = pvPortMalloc(size+4);
tx_buff[0] = FLASH_PROGRAM_PAGE;
tx_buff[1] = (address >> 16) & 0xFF;
tx_buff[2] = (address >> 8) & 0xFF;
tx_buff[3] = address & 0xFF;
memcpy(&tx_buff[4], data, size);
ssp_write( FLASH_SPI, &tx_buff[0], size+4 );
vPortFree(tx_buff);
}
void flash_sector_erase( uint32_t address )
{
uint8_t tx_buff[4];
tx_buff[0] = FLASH_SECTOR_ERASE;
tx_buff[1] = (address >> 16) & 0xFF;
tx_buff[2] = (address >> 8) & 0xFF;
tx_buff[3] = address & 0xFF;
flash_write_enable();
ssp_write( FLASH_SPI, tx_buff, sizeof(tx_buff) );
}
void flash_bulk_erase( void )
{
uint8_t tx_buff[1] = {FLASH_BULK_ERASE};
flash_write_enable();
ssp_write( FLASH_SPI, tx_buff, sizeof(tx_buff) );
}
uint8_t is_flash_busy( void )
{
uint8_t status = flash_read_status_reg();
return (status & 0x01);
}
/*
* openMMC -- Open Source modular IPM Controller firmware
*
* Copyright (C) 2015-2016 Henrique Silva <henrique.silva@lnls.br>
*
* 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 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* @license GPL-3.0+ <http://spdx.org/licenses/GPL-3.0+>
*/
#ifndef FLASH_SPI_H_
#define FLASH_SPI_H_
#define FLASH_SPI_BITRATE 1000000
#define FLASH_SPI_FRAME_SIZE 8
/* M25P128 Flash commands */
#define FLASH_WRITE_ENABLE 0x06
#define FLASH_WRITE_DISABLE 0x04
#define FLASH_READ_ID 0x9F
#define FLASH_READ_STATUS_REG 0x05
#define FLASH_WRITE_STATUS_REG 0x01
#define FLASH_READ_LOCK_REG 0xE8
#define FLASH_WRITE_LOCK_REG 0xE5
#define FLASH_READ_DATA 0x03
#define FLASH_FAST_READ_DATA 0x0B
#define FLASH_PROGRAM_PAGE 0x02
#define FLASH_SECTOR_ERASE 0xD8
#define FLASH_BULK_ERASE 0xC7
void flash_write_enable( void );
void flash_write_disable( void );
void flash_read_id( uint8_t * id_buffer, uint8_t buff_size );
uint8_t flash_read_status_reg( void );
void flash_write_status_reg( uint8_t data );
uint8_t flash_read_data( uint32_t address );
void flash_fast_read_data( uint32_t start_addr, uint8_t * dst, uint32_t size );
void flash_program_page( uint32_t address, uint8_t * data, uint16_t size );
void flash_sector_erase( uint32_t address );
void flash_bulk_erase( void );
uint8_t flash_read_lock_reg( uint32_t address );
void flash_write_lock_reg( uint32_t address, uint8_t data );
uint8_t is_flash_busy( void );
#endif
/*
* openMMC -- Open Source modular IPM Controller firmware
*
* Copyright (C) 2015 Julian Mendez <julian.mendez@cern.ch>
* Copyright (C) 2015-2016 Henrique Silva <henrique.silva@lnls.br>
*
* 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 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* @license GPL-3.0+ <http://spdx.org/licenses/GPL-3.0+>
*/
/*! @file fru.c /*! @file fru.c
* Creation of FRU information binary * Creation of FRU information binary
* Based on Julian Mendez implementation for CERN MMC * Based on Julian Mendez implementation for CERN MMC
...@@ -7,199 +29,197 @@ ...@@ -7,199 +29,197 @@
#include <string.h> #include <string.h>
#include "FreeRTOS.h" #include "FreeRTOS.h"
#include "ipmi.h" #include "utils.h"
#include "fru.h" #include "fru.h"
#include "user_fru.h" #include "user_fru.h"
uint8_t fru_data[FRU_SIZE]; uint8_t fru_data[FRU_SIZE];
void fru_header_function( uint8_t * fru_buffer ) void fru_header_build( uint8_t * fru_buffer )
{ {
t_fru_common_header * hdr = (t_fru_common_header *) fru_buffer; t_fru_common_header * hdr = (t_fru_common_header *) fru_buffer;
hdr->format_version = 0x01; hdr->format_version = 0x01;
#ifdef INTERNAL_USE_AREA_ENABLE #ifdef INTERNAL_USE_AREA_ENABLE
hdr->int_use_offset = INTERNAL_USE_AREA_OFFSET/8; hdr->int_use_offset = INTERNAL_USE_AREA_OFFSET/8;
#endif #endif
#ifdef CHASSIS_INFO_AREA_ENABLE #ifdef CHASSIS_INFO_AREA_ENABLE
hdr->chassis_info_offset = CHASSIS_INFO_AREA_OFFSET/8; hdr->chassis_info_offset = CHASSIS_INFO_AREA_OFFSET/8;
#endif #endif
#ifdef BOARD_INFO_AREA_ENABLE #ifdef BOARD_INFO_AREA_ENABLE
hdr->board_info_offset = BOARD_INFO_AREA_OFFSET/8; hdr->board_info_offset = BOARD_INFO_AREA_OFFSET/8;
#endif #endif
#ifdef PRODUCT_INFO_AREA_ENABLE #ifdef PRODUCT_INFO_AREA_ENABLE
hdr->product_info_offset = PRODUCT_INFO_AREA_OFFSET/8; hdr->product_info_offset = PRODUCT_INFO_AREA_OFFSET/8;
#endif #endif
#ifdef MULTIRECORD_AREA_ENABLE #ifdef MULTIRECORD_AREA_ENABLE
hdr->multirecord_offset = MULTIRECORD_AREA_OFFSET/8; hdr->multirecord_offset = MULTIRECORD_AREA_OFFSET/8;
#endif #endif
hdr->checksum = ipmb_calculate_chksum((uint8_t *) hdr, sizeof(t_fru_common_header)); hdr->checksum = calculate_chksum((uint8_t *) hdr, sizeof(t_fru_common_header));
} }
void board_info_area_function( uint8_t * fru_buffer ) void board_info_area_build( uint8_t * fru_buffer )
{ {
#ifdef BOARD_INFO_AREA_ENABLE #ifdef BOARD_INFO_AREA_ENABLE
t_board_area_format_hdr * board_ptr = (t_board_area_format_hdr *) fru_buffer; t_board_area_format_hdr * board_ptr = (t_board_area_format_hdr *) fru_buffer;
board_area_format_hdr * board_info = &(board_ptr->data); board_area_format_hdr * board_info = &(board_ptr->data);
/* Record Format version */ /* Record Format version */
board_info->format_version = 0x01; board_info->format_version = 0x01;
/* Record Length */ /* Record Length */
board_info->len = BOARD_INFO_AREA_SIZE/8; board_info->len = BOARD_INFO_AREA_SIZE/8;
/* Language Code */ /* Language Code */
board_info->lang_code = LANG_CODE; board_info->lang_code = LANG_CODE;
/* Manufacturing date/time - LS Byte first */ /* Manufacturing date/time - LS Byte first */
board_info->mfg_time[0] = 0x00; board_info->mfg_time[0] = 0x00;
board_info->mfg_time[1] = 0x00; board_info->mfg_time[1] = 0x00;
board_info->mfg_time[2] = 0x00; board_info->mfg_time[2] = 0x00;
/* Board Manufacturer */ /* Board Manufacturer */
board_info->manuf_type = 0x03; board_info->manuf_type = 0x03;
board_info->manuf_len = (strlen(BOARD_MANUFACTURER) & 0x3F); board_info->manuf_len = (strlen(BOARD_MANUFACTURER) & 0x3F);
#ifdef BOARD_MANUFACTURER #ifdef BOARD_MANUFACTURER
strncpy((char*)&(board_info->manuf), BOARD_MANUFACTURER, strlen(BOARD_MANUFACTURER)); strncpy((char*)&(board_info->manuf), BOARD_MANUFACTURER, strlen(BOARD_MANUFACTURER));
#endif #endif
/* Board Product Name */ /* Board Product Name */
board_info->prod_name_type = 0x03; board_info->prod_name_type = 0x03;
board_info->prod_name_len = (strlen(BOARD_NAME) & 0x3F); board_info->prod_name_len = (strlen(BOARD_NAME) & 0x3F);
#ifdef BOARD_NAME #ifdef BOARD_NAME
strncpy((char*) &(board_info->prod_name), BOARD_NAME, strlen(BOARD_NAME)); strncpy((char*) &(board_info->prod_name), BOARD_NAME, strlen(BOARD_NAME));
#endif #endif
/* Board Serial Number */ /* Board Serial Number */
board_info->ser_num_type = 0x03; board_info->ser_num_type = 0x03;
board_info->ser_num_len = (strlen(BOARD_SN) & 0x3F); board_info->ser_num_len = (strlen(BOARD_SN) & 0x3F);
#ifdef BOARD_SN #ifdef BOARD_SN
strncpy((char*) &(board_info->ser_num), BOARD_SN, strlen(BOARD_SN)); strncpy((char*) &(board_info->ser_num), BOARD_SN, strlen(BOARD_SN));
#endif #endif
/* Board Part Number */ /* Board Part Number */
board_info->part_num_type = 0x03; board_info->part_num_type = 0x03;
board_info->part_num_len = (strlen(BOARD_PN) & 0x3F); board_info->part_num_len = (strlen(BOARD_PN) & 0x3F);
#ifdef BOARD_PN #ifdef BOARD_PN
strncpy((char*) &(board_info->part_num), BOARD_PN, strlen(BOARD_PN)); strncpy((char*) &(board_info->part_num), BOARD_PN, strlen(BOARD_PN));
#endif #endif
/* FRU File ID */ /* FRU File ID */
board_info->fru_file_id_type = 0x03; board_info->fru_file_id_type = 0x03;
board_info->fru_file_id_len = (strlen(FRU_FILE_ID) & 0x3F); board_info->fru_file_id_len = (strlen(FRU_FILE_ID) & 0x3F);
#ifdef FRU_FILE_ID #ifdef FRU_FILE_ID
strncpy((char*) &(board_info->fru_file_id), FRU_FILE_ID, strlen(FRU_FILE_ID)); strncpy((char*) &(board_info->fru_file_id), FRU_FILE_ID, strlen(FRU_FILE_ID));
#endif #endif
/* No more info fields (End of record) */ /* No more info fields (End of record) */
board_info->end_of_record = 0xC1; board_info->end_of_record = 0xC1;
/* Checksum */ /* Checksum */
board_ptr->checksum = ipmb_calculate_chksum((uint8_t *)board_info, BOARD_INFO_AREA_SIZE); board_ptr->checksum = calculate_chksum((uint8_t *)board_info, BOARD_INFO_AREA_SIZE);
#endif #endif
} }
void product_info_area_function( uint8_t * fru_buffer ) void product_info_area_build( uint8_t * fru_buffer )
{ {
#ifdef PRODUCT_INFO_AREA_ENABLE #ifdef PRODUCT_INFO_AREA_ENABLE
t_product_area_format_hdr * product_ptr = (t_product_area_format_hdr *) fru_buffer; t_product_area_format_hdr * product_ptr = (t_product_area_format_hdr *) fru_buffer;
product_area_format_hdr * product_info = &(product_ptr->data); product_area_format_hdr * product_info = &(product_ptr->data);
/* Format Version */ /* Format Version */
product_info->format_version = 1; product_info->format_version = 1;
/* Record size in 8 bytes */ /* Record size in 8 bytes */
product_info->len = PRODUCT_INFO_AREA_SIZE/8; product_info->len = PRODUCT_INFO_AREA_SIZE/8;
/* Language code */ /* Language code */
product_info->lang_code = LANG_CODE; product_info->lang_code = LANG_CODE;
/* Product Manufacturer */ /* Product Manufacturer */
product_info->manuf_name_type = 0x3; product_info->manuf_name_type = 0x3;
product_info->manuf_name_len = (strlen(PRODUCT_MANUFACTURER) & 0x3F); product_info->manuf_name_len = (strlen(PRODUCT_MANUFACTURER) & 0x3F);
#ifdef PRODUCT_MANUFACTURER #ifdef PRODUCT_MANUFACTURER
strncpy((char*) &(product_info->manuf_name), PRODUCT_MANUFACTURER, strlen(PRODUCT_MANUFACTURER)); strncpy((char*) &(product_info->manuf_name), PRODUCT_MANUFACTURER, strlen(PRODUCT_MANUFACTURER));
#endif #endif
/* Product Name */ /* Product Name */
product_info->prod_name_type = 0x03; product_info->prod_name_type = 0x03;
product_info->prod_name_len = (strlen(PRODUCT_NAME) & 0x3F); product_info->prod_name_len = (strlen(PRODUCT_NAME) & 0x3F);
#ifdef PRODUCT_NAME #ifdef PRODUCT_NAME
strncpy((char*) &(product_info->prod_name), PRODUCT_NAME, strlen(PRODUCT_NAME)); strncpy((char*) &(product_info->prod_name), PRODUCT_NAME, strlen(PRODUCT_NAME));
#endif #endif
/* Product Part/Model Number type/length */ /* Product Part/Model Number type/length */
product_info->prod_part_model_num_type = 0x03; product_info->prod_part_model_num_type = 0x03;
product_info->prod_part_model_num_len = (strlen(PRODUCT_PN) & 0x3F); product_info->prod_part_model_num_len = (strlen(PRODUCT_PN) & 0x3F);
#ifdef PRODUCT_PN #ifdef PRODUCT_PN
strncpy((char*) &(product_info->prod_part_model), PRODUCT_PN, strlen(PRODUCT_PN)); strncpy((char*) &(product_info->prod_part_model), PRODUCT_PN, strlen(PRODUCT_PN));
#endif #endif
/* Product Version */ /* Product Version */
product_info->prod_version_type = 0x03; product_info->prod_version_type = 0x03;
product_info->prod_version_len = (strlen(PRODUCT_VERSION) & 0x3F); product_info->prod_version_len = (strlen(PRODUCT_VERSION) & 0x3F);
#ifdef PRODUCT_VERSION #ifdef PRODUCT_VERSION
strncpy((char*) &(product_info->prod_version), PRODUCT_VERSION, strlen(PRODUCT_VERSION)); strncpy((char*) &(product_info->prod_version), PRODUCT_VERSION, strlen(PRODUCT_VERSION));
#endif #endif
/* Product Serial Num */ /* Product Serial Num */
product_info->prod_serial_num_type = 0x03; product_info->prod_serial_num_type = 0x03;
product_info->prod_serial_num_len = (strlen(PRODUCT_SN) & 0x3F); product_info->prod_serial_num_len = (strlen(PRODUCT_SN) & 0x3F);
#ifdef PRODUCT_SN #ifdef PRODUCT_SN
strncpy((char*) &(product_info->prod_serial_num), PRODUCT_SN, strlen(PRODUCT_SN)); strncpy((char*) &(product_info->prod_serial_num), PRODUCT_SN, strlen(PRODUCT_SN));
#endif #endif
/* Product Serial Num */ /* Product Serial Num */
product_info->asset_tag_type = 0x03; product_info->asset_tag_type = 0x03;
product_info->asset_tag_len = (strlen(PRODUCT_ASSET_TAG) & 0x3F); product_info->asset_tag_len = (strlen(PRODUCT_ASSET_TAG) & 0x3F);
#ifdef PRODUCT_ASSET_TAG #ifdef PRODUCT_ASSET_TAG
strncpy((char*) &(product_info->asset_tag), PRODUCT_ASSET_TAG, strlen(PRODUCT_ASSET_TAG)); strncpy((char*) &(product_info->asset_tag), PRODUCT_ASSET_TAG, strlen(PRODUCT_ASSET_TAG));
#endif #endif
/* FRU File ID */ /* FRU File ID */
product_info->fru_file_id_type = 0x03; product_info->fru_file_id_type = 0x03;
product_info->fru_file_id_len = (strlen(FRU_FILE_ID) & 0x3F); product_info->fru_file_id_len = (strlen(FRU_FILE_ID) & 0x3F);
#ifdef FRU_FILE_ID #ifdef FRU_FILE_ID
strncpy((char*) &(product_info->fru_file_id), FRU_FILE_ID, strlen(FRU_FILE_ID)); strncpy((char*) &(product_info->fru_file_id), FRU_FILE_ID, strlen(FRU_FILE_ID));
#endif #endif
product_info->end_of_record = 0xC1; product_info->end_of_record = 0xC1;
product_ptr->checksum = ipmb_calculate_chksum((uint8_t *)product_info, PRODUCT_INFO_AREA_SIZE); product_ptr->checksum = calculate_chksum((uint8_t *)product_info, PRODUCT_INFO_AREA_SIZE);
#endif #endif
} }
void module_current_record_function( uint8_t * fru_buffer ) void module_current_record_build( uint8_t * fru_buffer )
{ {
#ifdef MODULE_CURRENT_RECORD #ifdef MODULE_CURRENT_RECORD
t_module_current_record * module_current_record = (t_module_current_record *) fru_buffer; t_module_current_record * module_current_record = (t_module_current_record *) fru_buffer;
/* Record Type ID */ /* Record Type ID */
module_current_record->hdr.record_type_id = 0xC0; //OEM Record module_current_record->hdr.record_type_id = 0xC0; //OEM Record
module_current_record->hdr.eol = 0x01; //Last Record module_current_record->hdr.eol = 0x01; //Last Record
module_current_record->hdr.version = 0x02; //Record format version module_current_record->hdr.version = 0x02; //Record format version
module_current_record->hdr.record_len = 0x06; //Record length module_current_record->hdr.record_len = sizeof(t_module_current_record)-sizeof(t_multirecord_area_header); //Record length
module_current_record->hdr.manuf_id[0] = 0x5A; module_current_record->manuf_id[0] = 0x5A;
module_current_record->hdr.manuf_id[1] = 0x31; module_current_record->manuf_id[1] = 0x31;
module_current_record->hdr.manuf_id[2] = 0x00; //Manufacturer ID (PICMG) module_current_record->manuf_id[2] = 0x00; //Manufacturer ID (PICMG)
module_current_record->hdr.picmg_rec_id = 0x16; //PICMG Record ID (19h - AMC Point to point connectivity) module_current_record->picmg_rec_id = 0x16; //PICMG Record ID (19h - AMC Point to point connectivity)
module_current_record->hdr.rec_fmt_ver = 0x00; //Record format version (0x00 for this version) module_current_record->rec_fmt_ver = 0x00; //Record format version (0x00 for this version)
/* Current Draw */ /* Current Draw */
module_current_record->current = MODULE_CURRENT_RECORD; module_current_record->current = MODULE_CURRENT_RECORD;
/* Checksums */ /* Checksums */
/* Record Checksum */ /* Record Checksum */
module_current_record->hdr.record_cksum = ipmb_calculate_chksum(&(module_current_record->hdr.manuf_id[0]), 6); module_current_record->hdr.record_cksum = calculate_chksum( ((uint8_t *)module_current_record)+sizeof(t_multirecord_area_header), module_current_record->hdr.record_len);
/* Header Checksum */ /* Header Checksum */
module_current_record->hdr.header_cksum = ipmb_calculate_chksum( (uint8_t *)&(module_current_record->hdr), 5); module_current_record->hdr.header_cksum = calculate_chksum( (uint8_t *)&(module_current_record->hdr), sizeof(t_multirecord_area_header));
#endif #endif
} }
void AMC_POINT_TO_POINT_RECORD_func( uint8_t * fru_buffer ) void amc_point_to_point_record_build( uint8_t * fru_buffer )
{ {
#ifdef CERN_FRU
#ifdef AMC_POINT_TO_POINT_RECORD_LIST #ifdef AMC_POINT_TO_POINT_RECORD_LIST
#ifndef POINT_TO_POINT_OEM_GUID_CNT #ifndef POINT_TO_POINT_OEM_GUID_CNT
...@@ -211,16 +231,17 @@ void AMC_POINT_TO_POINT_RECORD_func( uint8_t * fru_buffer ) ...@@ -211,16 +231,17 @@ void AMC_POINT_TO_POINT_RECORD_func( uint8_t * fru_buffer )
p2p_record->hdr.record_type_id = 0xC0; //OEM Record p2p_record->hdr.record_type_id = 0xC0; //OEM Record
p2p_record->hdr.eol = 0x00; //Record format version p2p_record->hdr.eol = 0x00; //Record format version
p2p_record->hdr.version = 0x02; //Record format version p2p_record->hdr.version = 0x02; //Record format version
p2p_record->hdr.record_len = sizeof(t_amc_point_to_point_record)-sizeof(t_multirecord_area_header);
p2p_record->hdr.manuf_id[0] = 0x5A; p2p_record->manuf_id[0] = 0x5A;
p2p_record->hdr.manuf_id[1] = 0x31; p2p_record->manuf_id[1] = 0x31;
p2p_record->hdr.manuf_id[2] = 0x00; //Manufacturer ID (PICMG) p2p_record->manuf_id[2] = 0x00; //Manufacturer ID (PICMG)
p2p_record->hdr.picmg_rec_id = 0x19; //PICMG Record ID (19h - AMC Point to point connectivity) p2p_record->picmg_rec_id = 0x19; //PICMG Record ID (19h - AMC Point to point connectivity)
p2p_record->hdr.rec_fmt_ver = 0x00; //Record format version (0x00 for this version) p2p_record->rec_fmt_ver = 0x00; //Record format version (0x00 for this version)
p2p_record->oem_guid_cnt = POINT_TO_POINT_OEM_GUID_CNT; //OEM Guid cnt p2p_record->oem_guid_cnt = POINT_TO_POINT_OEM_GUID_CNT; //OEM Guid cnt
#ifdef POINT_TO_POINT_OEM_GUID_LIST #ifdef POINT_TO_POINT_OEM_GUID_LIST
/* TODO: find a way to populate this list */ /* TODO: find a way to populate this list */
POINT_TO_POINT_OEM_GUID_LIST; POINT_TO_POINT_OEM_GUID_LIST;
#endif #endif
...@@ -228,86 +249,13 @@ void AMC_POINT_TO_POINT_RECORD_func( uint8_t * fru_buffer ) ...@@ -228,86 +249,13 @@ void AMC_POINT_TO_POINT_RECORD_func( uint8_t * fru_buffer )
AMC_POINT_TO_POINT_RECORD_LIST; AMC_POINT_TO_POINT_RECORD_LIST;
p2p_record->hdr.record_len = sizeof(t_amc_point_to_point_record)-5; p2p_record->hdr.record_cksum = calculate_chksum( ((uint8_t *)p2p_record)+sizeof(t_multirecord_area_header), p2p_record->hdr.record_len); //record checksum
p2p_record->hdr.record_cksum = ipmb_calculate_chksum(&(p2p_record->hdr.manuf_id[0]), (sizeof(t_amc_point_to_point_record)-5)); //record checksum p2p_record->hdr.header_cksum = calculate_chksum( (uint8_t *)&(p2p_record->hdr), sizeof(t_multirecord_area_header)); //Header checksum
p2p_record->hdr.header_cksum = ipmb_calculate_chksum( ( uint8_t *)&(p2p_record->hdr), 5); //Header checksum
#endif #endif
#else
t_amc_point_to_point_record *pP2PCon = (t_amc_point_to_point_record *) fru_buffer;
pP2PCon->record_type_id = 0xC0; /* For all records a value of C0h (OEM) shall be used. */
pP2PCon->eol = 0; /* [7:7] End of list. Set to one for the last record */
pP2PCon->reserved = 0; /* Reserved, write as 0h.*/
pP2PCon->version = 2; /* record format version (2h for this definition) */
pP2PCon->record_len = 47; /* Record Length. */
/* Manufacturer ID - For the AMC specification the value 12634 (00315Ah) must be used. */
pP2PCon->manuf_id[0] = 0x5A;
pP2PCon->manuf_id[1] = 0x31;
pP2PCon->manuf_id[2] = 0x00;
pP2PCon->picmg_rec_id = 0x19; /* 0x19 for AMC Point-to-Point Connectivity record */
pP2PCon->rec_fmt_ver = 0; /* Record Format Version, = 0 for this specification */
pP2PCon->oem_guid_count = 0; /* OEM GUID Count */
pP2PCon->record_type = 1; /* 1 = AMC Module */
pP2PCon->conn_dev_id = 0; /* Connected-device ID if Record Type = 0, Reserved, otherwise. */
pP2PCon->ch_descr_count = 3; /* AMC Channel Descriptor Count */
// AMC Link configuration for PCIe GEN1
pP2PCon->amc_ch_descr0[0] = 0x00;
pP2PCon->amc_ch_descr0[1] = 0x00;
pP2PCon->amc_ch_descr0[2] = 0x00;
pP2PCon->amc_ch_descr1[0] = 0xA4;
pP2PCon->amc_ch_descr1[1] = 0x98;
pP2PCon->amc_ch_descr1[2] = 0xF3;
pP2PCon->amc_ch_descr2[0] = 0xA4;
pP2PCon->amc_ch_descr2[1] = 0x98;
pP2PCon->amc_ch_descr2[2] = 0xF3;
pP2PCon->amc_link_descr0[0] = 0x00;
pP2PCon->amc_link_descr0[1] = 0x2F;
pP2PCon->amc_link_descr0[2] = 0x00;
pP2PCon->amc_link_descr0[3] = 0x00;
pP2PCon->amc_link_descr0[4] = 0xFD;
pP2PCon->amc_link_descr1[0] = 0x00;
pP2PCon->amc_link_descr1[1] = 0x2F;
pP2PCon->amc_link_descr1[2] = 0x10;
pP2PCon->amc_link_descr1[3] = 0x00;
pP2PCon->amc_link_descr1[4] = 0xFD;
pP2PCon->amc_link_descr2[0] = 0x00;
pP2PCon->amc_link_descr2[1] = 0x23;
pP2PCon->amc_link_descr2[2] = 0x00;
pP2PCon->amc_link_descr2[3] = 0x00;
pP2PCon->amc_link_descr2[4] = 0xFD;
pP2PCon->amc_link_descr3[0] = 0x00;
pP2PCon->amc_link_descr3[1] = 0x23;
pP2PCon->amc_link_descr3[2] = 0x10;
pP2PCon->amc_link_descr3[3] = 0x00;
pP2PCon->amc_link_descr3[4] = 0xFD;
pP2PCon->amc_link_descr4[0] = 0x01;
pP2PCon->amc_link_descr4[1] = 0x21;
pP2PCon->amc_link_descr4[2] = 0x00;
pP2PCon->amc_link_descr4[3] = 0x00;
pP2PCon->amc_link_descr4[4] = 0xFD;
pP2PCon->amc_link_descr5[0] = 0x01;
pP2PCon->amc_link_descr5[1] = 0x21;
pP2PCon->amc_link_descr5[2] = 0x10;
pP2PCon->amc_link_descr5[3] = 0x00;
pP2PCon->amc_link_descr5[4] = 0xFD;
pP2PCon->record_cksum = ipmb_calculate_chksum( ( uint8_t * )&( pP2PCon->manuf_id[0] ), 47 );
pP2PCon->header_cksum = ipmb_calculate_chksum( ( uint8_t * )&( pP2PCon->record_type_id ), 4 );
#endif
} }
void point_to_point_clock( uint8_t * fru_buffer ) void point_to_point_clock_build( uint8_t * fru_buffer )
{ {
#ifdef AMC_CLOCK_CONFIGURATION_LIST #ifdef AMC_CLOCK_CONFIGURATION_LIST
...@@ -316,12 +264,12 @@ void point_to_point_clock( uint8_t * fru_buffer ) ...@@ -316,12 +264,12 @@ void point_to_point_clock( uint8_t * fru_buffer )
clock_cfg->hdr.record_type_id = 0xC0; clock_cfg->hdr.record_type_id = 0xC0;
clock_cfg->hdr.eol = 0x00; clock_cfg->hdr.eol = 0x00;
clock_cfg->hdr.version = 0x02; clock_cfg->hdr.version = 0x02;
clock_cfg->hdr.record_len = sizeof(t_amc_clock_config_record)-5; clock_cfg->hdr.record_len = sizeof(t_amc_clock_config_record)-sizeof(t_multirecord_area_header);
clock_cfg->hdr.manuf_id[0] = 0x5A; clock_cfg->manuf_id[0] = 0x5A;
clock_cfg->hdr.manuf_id[1] = 0x31; clock_cfg->manuf_id[1] = 0x31;
clock_cfg->hdr.manuf_id[2] = 0x00; clock_cfg->manuf_id[2] = 0x00;
clock_cfg->hdr.picmg_rec_id = 0x2D; clock_cfg->picmg_rec_id = 0x2D;
clock_cfg->hdr.rec_fmt_ver = 0x00; clock_cfg->rec_fmt_ver = 0x00;
clock_cfg->resource_id = 0xFF; clock_cfg->resource_id = 0xFF;
...@@ -331,8 +279,8 @@ void point_to_point_clock( uint8_t * fru_buffer ) ...@@ -331,8 +279,8 @@ void point_to_point_clock( uint8_t * fru_buffer )
memcpy(clock_cfg->descriptor, &clock_descriptor_list, sizeof(clock_cfg->descriptor)); memcpy(clock_cfg->descriptor, &clock_descriptor_list, sizeof(clock_cfg->descriptor));
clock_cfg->hdr.record_cksum = ipmb_calculate_chksum((uint8_t*)&(clock_cfg->hdr.manuf_id[0]), clock_cfg->hdr.record_len); clock_cfg->hdr.record_cksum = calculate_chksum( ((uint8_t *)clock_cfg)+sizeof(t_multirecord_area_header), clock_cfg->hdr.record_len );
clock_cfg->hdr.header_cksum = ipmb_calculate_chksum((uint8_t*)&(clock_cfg->hdr), 5); clock_cfg->hdr.header_cksum = calculate_chksum( (uint8_t *)&(clock_cfg->hdr), sizeof(t_multirecord_area_header) );
#endif #endif
} }
...@@ -342,33 +290,35 @@ void fru_init( void ) ...@@ -342,33 +290,35 @@ void fru_init( void )
memset(&fru_data[0], 0, (sizeof(fru_data)/sizeof(fru_data[0]))); memset(&fru_data[0], 0, (sizeof(fru_data)/sizeof(fru_data[0])));
/* Populate the fru_buffer */ /* Populate the fru_buffer */
fru_header_function(&fru_data[COMMON_HEADER_OFFSET]); fru_header_build(&fru_data[COMMON_HEADER_OFFSET]);
board_info_area_function(&fru_data[BOARD_INFO_AREA_OFFSET]); board_info_area_build(&fru_data[BOARD_INFO_AREA_OFFSET]);
product_info_area_function(&fru_data[PRODUCT_INFO_AREA_OFFSET]); product_info_area_build(&fru_data[PRODUCT_INFO_AREA_OFFSET]);
AMC_POINT_TO_POINT_RECORD_func(&fru_data[AMC_POINT_TO_POINT_RECORD_OFFSET]); amc_point_to_point_record_build(&fru_data[AMC_POINT_TO_POINT_RECORD_OFFSET]);
point_to_point_clock(&fru_data[AMC_CLOCK_CONFIG_RECORD_OFFSET]); point_to_point_clock_build(&fru_data[AMC_CLOCK_CONFIG_RECORD_OFFSET]);
module_current_record_function(&fru_data[MODULE_CURRENT_RECORD_OFFSET]); module_current_record_build(&fru_data[MODULE_CURRENT_RECORD_OFFSET]);
} }
void fru_read_to_buffer(char *buff, int offset, int length) void fru_read_to_buffer(char *buff, uint8_t offset, uint8_t length)
{ {
uint8_t i; uint8_t i;
uint8_t j = offset; uint8_t j = offset;
for (i = 0; i<length; i++, j++ ) { for (i = 0; i<length; i++, j++ ) {
if (j < (sizeof(fru_data)/sizeof(fru_data[0]))) { if (j < (sizeof(fru_data)/sizeof(fru_data[0]))) {
buff[i] = fru_data[j]; buff[i] = fru_data[j];
} else { } else {
buff[i] = 0xFF; buff[i] = 0xFF;
} }
} }
} }
void fru_read_common_header(t_fru_common_header * header) { void fru_read_common_header(t_fru_common_header * header) {
fru_read_to_buffer( (char *) header, 0, sizeof(t_fru_common_header)); fru_read_to_buffer( (char *) header, 0, sizeof(t_fru_common_header));
} }
void ipmi_storage_get_fru_inventory( ipmi_msg * req, ipmi_msg * rsp ) /* IPMI Handlers */
IPMI_HANDLER(ipmi_storage_get_fru_info, NETFN_STORAGE, IPMI_GET_FRU_INVENTORY_AREA_INFO_CMD, ipmi_msg * req, ipmi_msg * rsp )
{ {
uint8_t len = rsp->data_len = 0; uint8_t len = rsp->data_len = 0;
rsp->data[len++] = FRU_SIZE & 0xFF; rsp->data[len++] = FRU_SIZE & 0xFF;
...@@ -378,7 +328,7 @@ void ipmi_storage_get_fru_inventory( ipmi_msg * req, ipmi_msg * rsp ) ...@@ -378,7 +328,7 @@ void ipmi_storage_get_fru_inventory( ipmi_msg * req, ipmi_msg * rsp )
rsp->completion_code = IPMI_CC_OK; rsp->completion_code = IPMI_CC_OK;
} }
void ipmi_storage_read_fru_data( ipmi_msg * req, ipmi_msg * rsp ) IPMI_HANDLER(ipmi_storage_read_fru_data_cmd, NETFN_STORAGE, IPMI_READ_FRU_DATA_CMD, ipmi_msg * req, ipmi_msg * rsp )
{ {
uint32_t offset; uint32_t offset;
uint8_t len = rsp->data_len = 0; uint8_t len = rsp->data_len = 0;
...@@ -387,9 +337,9 @@ void ipmi_storage_read_fru_data( ipmi_msg * req, ipmi_msg * rsp ) ...@@ -387,9 +337,9 @@ void ipmi_storage_read_fru_data( ipmi_msg * req, ipmi_msg * rsp )
uint8_t count = req->data[3]; uint8_t count = req->data[3];
if ( (count-1) > IPMI_MSG_MAX_LENGTH ) { if ( (count-1) > IPMI_MSG_MAX_LENGTH ) {
rsp->completion_code = IPMI_CC_CANT_RET_NUM_REQ_BYTES; rsp->completion_code = IPMI_CC_CANT_RET_NUM_REQ_BYTES;
return; return;
} }
offset = (req->data[2] << 8) | (req->data[1]); offset = (req->data[2] << 8) | (req->data[1]);
...@@ -399,3 +349,27 @@ void ipmi_storage_read_fru_data( ipmi_msg * req, ipmi_msg * rsp ) ...@@ -399,3 +349,27 @@ void ipmi_storage_read_fru_data( ipmi_msg * req, ipmi_msg * rsp )
rsp->data_len = len + count; rsp->data_len = len + count;
rsp->completion_code = IPMI_CC_OK; rsp->completion_code = IPMI_CC_OK;
} }
IPMI_HANDLER(ipmi_storage_write_fru_data_cmd, NETFN_STORAGE, IPMI_WRITE_FRU_DATA_CMD, ipmi_msg * req, ipmi_msg * rsp )
{
uint8_t len = rsp->data_len = 0;
uint16_t i;
uint16_t offset = (req->data[2] << 8) | (req->data[1]);
/* Use signed comparison here in case offset + data_len < 3 */
if ((offset + req->data_len - 3) < (int16_t)FRU_SIZE) {
for (i = 0; i< req->data_len-3; i++) {
fru_data[offset+i] = req->data[3+i];
}
/* Count written (1 based) */
rsp->data[len++] = i+1;
rsp->data_len = len;
rsp->completion_code = IPMI_CC_OK;
} else {
/* Count written (1 based) */
rsp->data[len++] = 0;
rsp->data_len = len;
rsp->completion_code = IPMI_CC_PARAM_OUT_OF_RANGE;
}
}
/* /*
* fru.h * openMMC -- Open Source modular IPM Controller firmware
* *
* Copyright (C) 2015 Julian Mendez <julian.mendez@cern.ch>
* Copyright (C) 2015-2016 Henrique Silva <henrique.silva@lnls.br>
*
* 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 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* @license GPL-3.0+ <http://spdx.org/licenses/GPL-3.0+>
*/ */
#ifndef FRU_H
#define FRU_H #ifndef FRU_H_
#define FRU_H_
#include "FreeRTOS.h" #include "FreeRTOS.h"
#include "string.h" #include "string.h"
#include "user_fru.h" #include "user_fru.h"
#include "ipmi.h"
#define MAX_FRU_SIZE 2048 #define MAX_FRU_SIZE 2048
...@@ -77,6 +96,7 @@ ...@@ -77,6 +96,7 @@
#define MATCHES_10 (0x02) #define MATCHES_10 (0x02)
#define PORT(n) n #define PORT(n) n
#define UNUSED_PORT 0x1F
#define current_in_ma(curr) (uint8_t)(curr/100); #define current_in_ma(curr) (uint8_t)(curr/100);
#define PADDING_SIZE(x) (7-(sizeof(x)%8)) #define PADDING_SIZE(x) (7-(sizeof(x)%8))
...@@ -133,13 +153,6 @@ typedef struct multirecord_area_header { ...@@ -133,13 +153,6 @@ typedef struct multirecord_area_header {
the record. */ the record. */
uint8_t header_cksum; /* Header Checksum. Holds the zero checksum of uint8_t header_cksum; /* Header Checksum. Holds the zero checksum of
the header. */ the header. */
uint8_t manuf_id[3]; /* Manufacturer ID. LS Byte first. Write as the
three byte ID assigned to PICMG®. For this
specification, the value 12634 (00315Ah) shall
be used. */
uint8_t picmg_rec_id; /* PICMG Record ID. */
uint8_t rec_fmt_ver; /* Record Format Version. For this specification,
the value 0h shall be used. */
} t_multirecord_area_header; } t_multirecord_area_header;
...@@ -335,34 +348,64 @@ typedef struct t_product_area_format_hdr { ...@@ -335,34 +348,64 @@ typedef struct t_product_area_format_hdr {
uint8_t checksum; // Product Info Area Checksum (zero checksum) uint8_t checksum; // Product Info Area Checksum (zero checksum)
} t_product_area_format_hdr; } t_product_area_format_hdr;
typedef struct module_current_record { typedef struct module_current_record {
t_multirecord_area_header hdr; t_multirecord_area_header hdr;
uint8_t manuf_id[3]; /* Manufacturer ID. LS Byte first. Write as the
three byte ID assigned to PICMG®. For this
specification, the value 12634 (00315Ah) shall
be used. */
uint8_t picmg_rec_id; /* PICMG Record ID. */
uint8_t rec_fmt_ver; /* Record Format Version. For this specification,
the value 0h shall be used. */
uint8_t current; uint8_t current;
} t_module_current_record; } t_module_current_record;
typedef struct __attribute__ ((__packed__)) amc_channel_descriptor { typedef struct __attribute__ ((__packed__)) amc_channel_descriptor {
/* LSB First */ #ifdef BF_MS_FIRST
uint8_t reserved:4;
uint8_t lane3:5;
uint8_t lane2:5;
uint8_t lane1:5;
uint8_t lane0:5;
#else
uint8_t lane0:5; uint8_t lane0:5;
uint8_t lane1:5; uint8_t lane1:5;
uint8_t lane2:5; uint8_t lane2:5;
uint8_t lane3:5; uint8_t lane3:5;
uint8_t reserved:4; uint8_t reserved:4;
#endif
} t_amc_channel_descriptor; } t_amc_channel_descriptor;
typedef struct __attribute__ ((__packed__)) amc_link_descriptor { typedef struct __attribute__ ((__packed__)) amc_link_descriptor {
/* LSB First */ /* LSB First */
#ifdef BF_MS_FIRST
uint8_t reserved:6,
assymetric_match:2;
uint8_t link_grouping_id;
uint16_t link_type_ext:4,
link_type:12;
uint8_t amc_channel_id; uint8_t amc_channel_id;
uint16_t link_type:12, #else
uint8_t amc_channel_id;
uint16_t lane_bit_flag:4,
link_type:8,
link_type_ext:4; link_type_ext:4;
uint8_t link_grouping_id; uint8_t link_grouping_id;
uint8_t reserved:6, uint8_t assymetric_match:2,
assymetric_match:2; reserved:6;
#endif
} t_amc_link_descriptor; } t_amc_link_descriptor;
#ifdef CERN_FRU
typedef struct amc_point_to_point_record { typedef struct amc_point_to_point_record {
t_multirecord_area_header hdr; t_multirecord_area_header hdr;
uint8_t manuf_id[3]; /* Manufacturer ID. LS Byte first. Write as the
three byte ID assigned to PICMG®. For this
specification, the value 12634 (00315Ah) shall
be used. */
uint8_t picmg_rec_id; /* PICMG Record ID. */
uint8_t rec_fmt_ver; /* Record Format Version. For this specification,
the value 0h shall be used. */
uint8_t oem_guid_cnt; uint8_t oem_guid_cnt;
#ifdef POINT_TO_POINT_OEM_GUID_LIST #ifdef POINT_TO_POINT_OEM_GUID_LIST
#if (POINT_TO_POINT_OEM_GUID_CNT == 0) #if (POINT_TO_POINT_OEM_GUID_CNT == 0)
...@@ -371,13 +414,13 @@ typedef struct amc_point_to_point_record { ...@@ -371,13 +414,13 @@ typedef struct amc_point_to_point_record {
uint8_t oem_guid_list[16*POINT_TO_POINT_OEM_GUID_CNT]; uint8_t oem_guid_list[16*POINT_TO_POINT_OEM_GUID_CNT];
#endif #endif
#ifdef BF_MS_FIRST #ifdef BF_MS_FIRST
uint8_t connected_dev_id:4,
reserved:3,
record_type:1;
#else
uint8_t record_type:1, /* [7] Record Type - 1 AMC-Module, 0 On-Carrier Device */ uint8_t record_type:1, /* [7] Record Type - 1 AMC-Module, 0 On-Carrier Device */
reserved:3, /* [6:4] Reserved, write as 0h.*/ reserved:3, /* [6:4] Reserved, write as 0h.*/
connected_dev_id:4; /* [3:0] Connected Dev ID if Record-Type =0, reserved, otherwise */ connected_dev_id:4; /* [3:0] Connected Dev ID if Record-Type =0, reserved, otherwise */
#else
uint8_t connected_dev_id:4,
reserved:3,
record_type:1;
#endif #endif
uint8_t amc_channel_descriptor_cnt; uint8_t amc_channel_descriptor_cnt;
...@@ -388,53 +431,6 @@ typedef struct amc_point_to_point_record { ...@@ -388,53 +431,6 @@ typedef struct amc_point_to_point_record {
} t_amc_point_to_point_record; } t_amc_point_to_point_record;
#define AMC_POINT_TO_POINT_RECORD_BUILD #define AMC_POINT_TO_POINT_RECORD_BUILD
#else
typedef struct amc_point_to_point_record {
/* AMC Table 3-16 AdvancedMC Point-to-Point Connectivity record */
uint8_t record_type_id; /* Record Type ID. For all records defined
in this specification a value of C0h (OEM)
shall be used. */
uint8_t version:4,
reserved:3,
eol:1;
uint8_t record_len; /* Record Length. # of bytes following rec cksum */
uint8_t record_cksum; /* Record Checksum. Holds the zero checksum of
the record. */
uint8_t header_cksum; /* Header Checksum. Holds the zero checksum of
the header. */
uint8_t manuf_id[3]; /* Manufacturer ID. LS Byte first. Write as the
three byte ID assigned to PICMG�. For this
specification, the value 12634 (00315Ah) shall
be used. */
uint8_t picmg_rec_id; /* PICMG Record ID. For the AMC Point-to-Point
Connectivity record, the value 19h must be used */
uint8_t rec_fmt_ver; /* Record Format Version. For this specification,
the value 0h shall be used. */
uint8_t oem_guid_count; /* OEM GUID Count. The number, n, of OEM GUIDs
defined in this record. */
//OEM_GUID oem_guid_list[n];
/* A list 16*n bytes of OEM GUIDs. */
uint8_t conn_dev_id:4,
:3,
record_type:1;
uint8_t ch_descr_count; /* AMC Channel Descriptor Count. The number, m,
of AMC Channel Descriptors defined in this record. */
uint8_t amc_ch_descr0[3];
uint8_t amc_ch_descr1[3];
uint8_t amc_ch_descr2[3];
uint8_t amc_link_descr0[5];
uint8_t amc_link_descr1[5];
uint8_t amc_link_descr2[5];
uint8_t amc_link_descr3[5];
uint8_t amc_link_descr4[5];
uint8_t amc_link_descr5[5];
} t_amc_point_to_point_record;
#endif
typedef struct indirect_clock_descriptor { typedef struct indirect_clock_descriptor {
#ifdef BF_MS_FIRST #ifdef BF_MS_FIRST
...@@ -466,7 +462,6 @@ typedef struct direct_clock_descriptor { ...@@ -466,7 +462,6 @@ typedef struct direct_clock_descriptor {
uint8_t clock_maximum_frequency[4]; uint8_t clock_maximum_frequency[4];
} t_direct_clock_descriptor; } t_direct_clock_descriptor;
typedef struct clock_config_descriptor { typedef struct clock_config_descriptor {
uint8_t clock_id; uint8_t clock_id;
#ifdef BF_MS_FIRST #ifdef BF_MS_FIRST
...@@ -485,6 +480,13 @@ typedef struct clock_config_descriptor { ...@@ -485,6 +480,13 @@ typedef struct clock_config_descriptor {
typedef struct amc_clock_config_record { typedef struct amc_clock_config_record {
t_multirecord_area_header hdr; t_multirecord_area_header hdr;
uint8_t manuf_id[3]; /* Manufacturer ID. LS Byte first. Write as the
three byte ID assigned to PICMG®. For this
specification, the value 12634 (00315Ah) shall
be used. */
uint8_t picmg_rec_id; /* PICMG Record ID. */
uint8_t rec_fmt_ver; /* Record Format Version. For this specification,
the value 0h shall be used. */
uint8_t resource_id; uint8_t resource_id;
uint8_t descriptor_cnt; uint8_t descriptor_cnt;
#ifdef AMC_CLOCK_CONFIGURATION_DESCRIPTORS_CNT #ifdef AMC_CLOCK_CONFIGURATION_DESCRIPTORS_CNT
...@@ -510,6 +512,7 @@ typedef struct amc_clock_config_record { ...@@ -510,6 +512,7 @@ typedef struct amc_clock_config_record {
#define AMC_CLOCK_CONFIGURATION_LIST_BUILD \ #define AMC_CLOCK_CONFIGURATION_LIST_BUILD \
t_clock_config_descriptor clock_descriptor_list[] = { AMC_CLOCK_CONFIGURATION_LIST } t_clock_config_descriptor clock_descriptor_list[] = { AMC_CLOCK_CONFIGURATION_LIST }
/* TODO: Lanes with value 0x31 should not be included in the lane bit flag */
#define GENERIC_POINT_TO_POINT_RECORD(id, port0, port1, port2, port3, protocol, extension, matches) \ #define GENERIC_POINT_TO_POINT_RECORD(id, port0, port1, port2, port3, protocol, extension, matches) \
p2p_record->amc_channel_descriptor_cnt++; \ p2p_record->amc_channel_descriptor_cnt++; \
p2p_record->amc_channel_descriptor[id].lane0 = port0; \ p2p_record->amc_channel_descriptor[id].lane0 = port0; \
...@@ -518,7 +521,8 @@ typedef struct amc_clock_config_record { ...@@ -518,7 +521,8 @@ typedef struct amc_clock_config_record {
p2p_record->amc_channel_descriptor[id].lane3 = port3; \ p2p_record->amc_channel_descriptor[id].lane3 = port3; \
p2p_record->amc_channel_descriptor[id].reserved = 0xF; \ p2p_record->amc_channel_descriptor[id].reserved = 0xF; \
p2p_record->amc_link_descriptor[id].amc_channel_id = id; \ p2p_record->amc_link_descriptor[id].amc_channel_id = id; \
p2p_record->amc_link_descriptor[id].link_type = (protocol<<4)|0xF; \ p2p_record->amc_link_descriptor[id].lane_bit_flag = 0xF; \
p2p_record->amc_link_descriptor[id].link_type = protocol; \
p2p_record->amc_link_descriptor[id].link_type_ext = extension; \ p2p_record->amc_link_descriptor[id].link_type_ext = extension; \
p2p_record->amc_link_descriptor[id].link_grouping_id = 0; \ p2p_record->amc_link_descriptor[id].link_grouping_id = 0; \
p2p_record->amc_link_descriptor[id].assymetric_match = matches; \ p2p_record->amc_link_descriptor[id].assymetric_match = matches; \
...@@ -591,18 +595,15 @@ typedef struct amc_clock_config_record { ...@@ -591,18 +595,15 @@ typedef struct amc_clock_config_record {
extern uint8_t fru_data[FRU_SIZE]; extern uint8_t fru_data[FRU_SIZE];
void module_current_record_function( uint8_t * fru_buffer );
void board_info_area_function( uint8_t * fru_buffer );
void product_info_area_function( uint8_t * fru_buffer );
void point_to_point_clock( uint8_t * fru_buffer );
void fru_header_function( uint8_t * fru_buffer );
void fru_init( void ); void fru_init( void );
void fru_header_build( uint8_t * fru_buffer );
void board_info_area_build( uint8_t * fru_buffer );
void product_info_area_build( uint8_t * fru_buffer );
void amc_point_to_point_record_build( uint8_t * fru_buffer );
void point_to_point_clock_build( uint8_t * fru_buffer );
void module_current_record_build( uint8_t * fru_buffer );
/* IPMI Handlers */ /* IPMI Handlers */
#include "ipmi.h" void fru_read_to_buffer(char *buff, uint8_t offset, uint8_t length);
void fru_read_to_buffer(char *buff, int offset, int length);
void fru_read_common_header(t_fru_common_header * header); void fru_read_common_header(t_fru_common_header * header);
void ipmi_storage_get_fru_info ( ipmi_msg * req, ipmi_msg * rsp);
void ipmi_storage_read_fru_data_cmd ( ipmi_msg * req, ipmi_msg * rsp);
#endif #endif
/*
* openMMC -- Open Source modular IPM Controller firmware
*
* Copyright (C) 2015-2016 Henrique Silva <henrique.silva@lnls.br>
*
* 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 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* @license GPL-3.0+ <http://spdx.org/licenses/GPL-3.0+>
*/
/* Project includes */
#include "ipmi.h"
#include "hpm.h"
#include "utils.h"
#include "string.h"
#include "led.h"
#include "payload.h"
#include "port.h"
/* Local Variables */
/* Stores the code of the current or last completed long duration command */
static uint8_t cmd_in_progress;
/* Stores the completion code of the current or last completed long duration command */
static uint8_t last_cmd_cc;
/*Current component under upgrade */
static uint8_t active_id;
/* IPMC Capabilities */
t_ipmc_capabilities ipmc_cap = {
.flags = { .upgrade_undesirable = 0,
.automatic_rollback_overridden = 0,
.ipmc_degraded_in_update = 0,
.deferred_activation = 1,
.services_affected = 1,
.manual_rollback = 1,
.automatic_rollback = 1,
.self_test = 1
}
};
/* Components properties */
t_component hpm_components[HPM_MAX_COMPONENTS] = {
[HPM_BOOTLOADER_COMPONENT_ID] = {
.properties = {
.flags = {
.reserved = 0x00,
.cold_reset_required = 1,
.deferred_activation_supported = 0,
.comparison_supported = 1,
.preparation_support = 0,
.rollback_backup_support = 0x01
}
},
},
[HPM_IPMC_COMPONENT_ID] = {
.properties = {
.flags = {
.reserved = 0x00,
.cold_reset_required = 1,
.deferred_activation_supported = 0,
.comparison_supported = 1,
.preparation_support = 0,
.rollback_backup_support = 0x01
}
},
.hpm_prepare_comp_f = ipmc_hpm_prepare_comp,
.hpm_upload_block_f = ipmc_hpm_upload_block,
.hpm_finish_upload_f = ipmc_hpm_finish_upload,
.hpm_get_upgrade_status_f = ipmc_hpm_get_upgrade_status,
.hpm_activate_firmware_f = ipmc_hpm_activate_firmware
},
[HPM_PAYLOAD_COMPONENT_ID] = {
.properties = {
.flags = {
.reserved = 0x00,
.cold_reset_required = 1,
.deferred_activation_supported = 0,
.comparison_supported = 1,
.preparation_support = 1,
.rollback_backup_support = 0x01
}
},
.hpm_prepare_comp_f = payload_hpm_prepare_comp,
.hpm_upload_block_f = payload_hpm_upload_block,
.hpm_finish_upload_f = payload_hpm_finish_upload,
.hpm_get_upgrade_status_f = payload_hpm_get_upgrade_status,
.hpm_activate_firmware_f = payload_hpm_activate_firmware
}
};
/*******************************************************/
void hpm_init( void )
{
memcpy(hpm_components[HPM_BOOTLOADER_COMPONENT_ID].description, "Bootloader", sizeof("Bootloader"));
memcpy(hpm_components[HPM_IPMC_COMPONENT_ID].description, "MMC", sizeof("MMC"));
memcpy(hpm_components[HPM_PAYLOAD_COMPONENT_ID].description, "Payload", sizeof("Payload"));
}
IPMI_HANDLER(ipmi_picmg_get_upgrade_capabilities, NETFN_GRPEXT, IPMI_PICMG_CMD_HPM_GET_UPGRADE_CAPABILITIES, ipmi_msg *req, ipmi_msg* rsp)
{
uint8_t len = rsp->data_len = 0;
rsp->data[len++] = IPMI_PICMG_GRP_EXT;
rsp->data[len++] = HPM_SUPPORTED_VERSION;
rsp->data[len++] = ipmc_cap.byte;
rsp->data[len++] = HPM_UPGRADE_TIMEOUT;
rsp->data[len++] = HPM_SELF_TEST_TIMEOUT;
rsp->data[len++] = HPM_ROLLBACK_TIMEOUT;
rsp->data[len++] = HPM_INACCESSIBILITY_TIMEOUT;
rsp->data[len++] = (1 << HPM_BOOTLOADER_COMPONENT_ID | 1 << HPM_IPMC_COMPONENT_ID | 1 << HPM_PAYLOAD_COMPONENT_ID);
rsp->data_len = len;
rsp->completion_code = IPMI_CC_OK;
/* This is not a long-duration command, so we don't need to update neither cmd_in_progress nor last_cmd_cc variables */
}
IPMI_HANDLER(ipmi_picmg_get_component_properties, NETFN_GRPEXT, IPMI_PICMG_CMD_HPM_GET_COMPONENT_PROPERTIES, ipmi_msg *req, ipmi_msg* rsp)
{
uint8_t len = rsp->data_len = 0;
uint8_t comp_id = req->data[1];
uint8_t comp_properties_selector = req->data[2];
rsp->completion_code = IPMI_CC_UNSPECIFIED_ERROR;
if (comp_id > 7) {
rsp->data[len++] = IPMI_PICMG_GRP_EXT;
/* Return command-specific completion code: 0x82 (Invalid Component ID) */
rsp->data_len = len;
rsp->completion_code = 0x82;
return;
}
rsp->data[len++] = IPMI_PICMG_GRP_EXT;
switch (comp_properties_selector) {
case 0x00:
/* General component properties */
rsp->data[len++] = hpm_components[comp_id].properties.byte;
rsp->completion_code = IPMI_CC_OK;
break;
case 0x01:
/* Firmware current version */
/* TODO: Read fw revision from flash */
rsp->data[len++] = (0x7F & FW_REV_MAJOR);
rsp->data[len++] = FW_REV_MINOR;
rsp->data[len++] = FW_REV_AUX_0;
rsp->data[len++] = FW_REV_AUX_1;
rsp->data[len++] = FW_REV_AUX_2;
rsp->data[len++] = FW_REV_AUX_3;
rsp->completion_code = IPMI_CC_OK;
break;
case 0x02:
/* Description string */
memcpy( &rsp->data[len], &hpm_components[comp_id].description[0], 12 );
len += 12;
rsp->completion_code = IPMI_CC_OK;
break;
case 0x03:
/* Rollback Firmware version */
/* TODO: Read fw revision from flash */
rsp->data[len++] = (0x7F & FW_REV_MAJOR);
rsp->data[len++] = FW_REV_MINOR;
rsp->data[len++] = FW_REV_AUX_0;
rsp->data[len++] = FW_REV_AUX_1;
rsp->data[len++] = FW_REV_AUX_2;
rsp->data[len++] = FW_REV_AUX_3;
rsp->completion_code = IPMI_CC_OK;
break;
case 0x04:
/* Deferred upgrade Firmware version */
/* TODO: Read fw revision from flash */
rsp->data[len++] = (0x7F & FW_REV_MAJOR);
rsp->data[len++] = FW_REV_MINOR;
rsp->data[len++] = FW_REV_AUX_0;
rsp->data[len++] = FW_REV_AUX_1;
rsp->data[len++] = FW_REV_AUX_2;
rsp->data[len++] = FW_REV_AUX_3;
rsp->completion_code = IPMI_CC_OK;
break;
default:
/* Return command-specific completion code: 0x83 (Invalid Component properties selector) */
rsp->completion_code = 0x83;
}
rsp->data_len = len;
/* This is not a long-duration command, so we don't need to update neither cmd_in_progress nor last_cmd_cc variables */
}
IPMI_HANDLER(ipmi_picmg_initiate_upgrade_action, NETFN_GRPEXT, IPMI_PICMG_CMD_HPM_INITIATE_UPGRADE_ACTION, ipmi_msg *req, ipmi_msg* rsp)
{
uint8_t len = rsp->data_len = 0;
uint8_t comp_id = req->data[1];
uint8_t upgrade_action = req->data[2];
rsp->completion_code = IPMI_CC_UNSPECIFIED_ERROR;
if (comp_id > 7) {
/* Component ID out of range */
rsp->data[len++] = IPMI_PICMG_GRP_EXT;
/* Return command-specific completion code: 0x82 (Invalid Component ID) */
rsp->data_len = len;
rsp->completion_code = 0x82;
return;
}
active_id = comp_id;
rsp->data[len++] = IPMI_PICMG_GRP_EXT;
switch (upgrade_action) {
case 0x00:
/* Backup component */
break;
case 0x01:
/* Prepare Component */
if (hpm_components[active_id].hpm_prepare_comp_f) {
rsp->completion_code = hpm_components[active_id].hpm_prepare_comp_f();
}
break;
case 0x02:
/* Upload for upgrade */
/* Set the component that'll be upgraded */
active_id = comp_id;
if (hpm_components[active_id].hpm_prepare_comp_f) {
rsp->completion_code = hpm_components[active_id].hpm_prepare_comp_f();
}
break;
case 0x03:
/* Upload for compare */
break;
default:
break;
}
rsp->data_len = len;
/* This is a long-duration command, update both cmd_in_progress and last_cmd_cc */
cmd_in_progress = req->cmd;
last_cmd_cc = rsp->completion_code;
}
IPMI_HANDLER(ipmi_picmg_get_upgrade_status, NETFN_GRPEXT, IPMI_PICMG_CMD_HPM_GET_UPGRADE_STATUS, ipmi_msg *req, ipmi_msg* rsp)
{
uint8_t len = rsp->data_len = 0;
if (hpm_components[active_id].hpm_get_upgrade_status_f) {
/* WARNING: This function can't block! */
last_cmd_cc = hpm_components[active_id].hpm_get_upgrade_status_f();
} else {
/* Returning IPMI_CC_OK for debug purposes only, should be IPMI_CC_UNSPECIFIED_ERROR */
last_cmd_cc = IPMI_CC_OK;
}
rsp->data[len++] = IPMI_PICMG_GRP_EXT;
rsp->data[len++] = cmd_in_progress;
rsp->data[len++] = last_cmd_cc;
rsp->data_len = len;
rsp->completion_code = IPMI_CC_OK;
/* This is not a long-duration command, so we don't need to update neither cmd_in_progress nor last_cmd_cc variables */
}
IPMI_HANDLER(ipmi_picmg_abort_firmware_upgrade, NETFN_GRPEXT, IPMI_PICMG_CMD_HPM_ABORT_FIRMWARE_UPGRADE, ipmi_msg *req, ipmi_msg* rsp)
{
uint8_t len = rsp->data_len = 0;
rsp->data[len++] = IPMI_PICMG_GRP_EXT;
rsp->data_len = len;
rsp->completion_code = IPMI_CC_OK;
/* This is not a long-duration command, so we don't need to update neither cmd_in_progress nor last_cmd_cc variables */
}
IPMI_HANDLER(ipmi_picmg_upload_firmware_block, NETFN_GRPEXT, IPMI_PICMG_CMD_HPM_UPLOAD_FIRMWARE_BLOCK, ipmi_msg *req, ipmi_msg* rsp)
{
uint8_t len = rsp->data_len = 0;
uint8_t block_data[HPM_BLOCK_SIZE];
if (active_id > 7) {
/* Component ID out of range */
rsp->data[len++] = IPMI_PICMG_GRP_EXT;
/* Return command-specific completion code: 0x81 (Invalid Component ID) */
rsp->data_len = len;
rsp->completion_code = 0x81;
return;
}
memcpy(&block_data[0], &req->data[2], req->data_len-2);
/* TODO: perform checksum of the block */
if (hpm_components[active_id].hpm_upload_block_f) {
/* WARNING: This function can't block! */
rsp->completion_code = hpm_components[active_id].hpm_upload_block_f(&block_data[0], sizeof(block_data));
} else {
rsp->completion_code = IPMI_CC_UNSPECIFIED_ERROR;
}
rsp->data[len++] = IPMI_PICMG_GRP_EXT;
rsp->data_len = len;
/* This is a long-duration command, update both cmd_in_progress and last_cmd_cc */
cmd_in_progress = req->cmd;
last_cmd_cc = rsp->completion_code;
}
IPMI_HANDLER(ipmi_picmg_finish_firmware_upload, NETFN_GRPEXT, IPMI_PICMG_CMD_HPM_FINISH_FIRMWARE_UPLOAD, ipmi_msg *req, ipmi_msg* rsp)
{
uint8_t len = rsp->data_len = 0;
uint32_t image_len = (req->data[5] << 24) | (req->data[4] << 16) | (req->data[3] << 8) | (req->data[2]);
/* TODO: implement HPM.1 REQ3.59 */
if ( hpm_components[active_id].hpm_finish_upload_f) {
rsp->completion_code = hpm_components[active_id].hpm_finish_upload_f( image_len );
} else {
rsp->completion_code = IPMI_CC_UNSPECIFIED_ERROR;
}
rsp->data[len++] = IPMI_PICMG_GRP_EXT;
rsp->data_len = len;
/* This is a long-duration command, update both cmd_in_progress and last_cmd_cc */
cmd_in_progress = req->cmd;
last_cmd_cc = rsp->completion_code;
}
IPMI_HANDLER(ipmi_picmg_activate_firmware, NETFN_GRPEXT, IPMI_PICMG_CMD_HPM_ACTIVATE_FIRMWARE, ipmi_msg *req, ipmi_msg* rsp)
{
uint8_t len = rsp->data_len = 0;
/* TODO: Compare firmware revisions before activating */
if (hpm_components[active_id].hpm_activate_firmware_f) {
rsp->completion_code = hpm_components[active_id].hpm_activate_firmware_f();
} else {
rsp->completion_code = IPMI_CC_UNSPECIFIED_ERROR;
}
rsp->data[len++] = IPMI_PICMG_GRP_EXT;
rsp->data_len = len;
/* This is a long-duration command, update both cmd_in_progress and last_cmd_cc */
cmd_in_progress = req->cmd;
last_cmd_cc = rsp->completion_code;
}
/*
* openMMC -- Open Source modular IPM Controller firmware
*
* Copyright (C) 2015-2016 Henrique Silva <henrique.silva@lnls.br>
*
* 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 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* @license GPL-3.0+ <http://spdx.org/licenses/GPL-3.0+>
*/
#ifndef HPM_H_
#define HPM_H_
#define HPM_SUPPORTED_VERSION 0x00
#define FW_REV_MAJOR 1 /* Binary encoded */
#define FW_REV_MINOR 0 /* BCD encoded */
#define FW_REV_AUX_0 0
#define FW_REV_AUX_1 0
#define FW_REV_AUX_2 0
#define FW_REV_AUX_3 0
#define HPM_UPGRADE_TIMEOUT 10 /* in 5 seconds counts */
#define HPM_SELF_TEST_TIMEOUT 5 /* in 5 seconds counts */
#define HPM_ROLLBACK_TIMEOUT 10 /* in 5 seconds counts */
#define HPM_INACCESSIBILITY_TIMEOUT 10 /* in 5 seconds counts */
#define IPMC_UPDATE_SECTOR_START 0x10
#define IPMC_UPDATE_SECTOR_END 0x11
#define IPMC_UPDATE_ADDRESS_OFFSET (IPMC_UPDATE_SECTOR_START << 12)
#define HPM_BLOCK_SIZE 20
/* Components ID */
enum {
HPM_BOOTLOADER_COMPONENT_ID = 0,
HPM_IPMC_COMPONENT_ID,
HPM_PAYLOAD_COMPONENT_ID,
HPM_MAX_COMPONENTS
};
typedef uint8_t (* t_hpm_upload_block)(uint8_t * block, uint16_t size);
typedef uint8_t (* t_hpm_finish_upload)(uint32_t image_size);
typedef uint8_t (* t_hpm_prepare_comp)(void);
typedef uint8_t (* t_hpm_get_upgrade_status)(void);
typedef uint8_t (* t_hpm_activate_firmware)(void);
typedef union {
struct {
uint8_t upgrade_undesirable:1;
uint8_t automatic_rollback_overridden:1;
uint8_t ipmc_degraded_in_update:1;
uint8_t deferred_activation:1;
uint8_t services_affected:1;
uint8_t manual_rollback:1;
uint8_t automatic_rollback:1;
uint8_t self_test:1;
} flags;
uint8_t byte;
} t_ipmc_capabilities;
typedef union __attribute__ ((__packed__)) {
struct {
uint8_t reserved:2,
cold_reset_required:1,
deferred_activation_supported:1,
comparison_supported:1,
preparation_support:1,
rollback_backup_support:2;
} flags;
uint8_t byte;
} t_comp_properties;
typedef struct {
t_comp_properties properties;
char description[12];
t_hpm_prepare_comp hpm_prepare_comp_f;
t_hpm_upload_block hpm_upload_block_f;
t_hpm_finish_upload hpm_finish_upload_f;
t_hpm_get_upgrade_status hpm_get_upgrade_status_f;
t_hpm_activate_firmware hpm_activate_firmware_f;
} t_component;
#endif
/*
* AFCIPMI --
*
* Copyright (C) 2015 Henrique Silva <henrique.silva@lnls.br>
*
* 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 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*!
* @file i2c.c
* @author Henrique Silva <henrique.silva@lnls.br>, LNLS
* @date August 2015
*
* @brief Implementation of a generic I2C driver using FreeRTOS features
*/
/* FreeRTOS includes */
#include "FreeRTOS.h"
/* Project includes */
#include "i2c.h"
#include "pin_mapping.h"
#include "port.h"
void vI2CInit( I2C_ID_T i2c_id, uint32_t speed, I2C_Mode mode )
{
/* Enable and configure I2C clock */
vI2CConfig( i2c_id, speed );
if ( mode == I2C_Mode_IPMB ) {
/* Configure Slave Address */
ipmb_addr = get_ipmb_addr( );
vI2CSlaveSetup( i2c_id, ipmb_addr );
}
} /* End of vI2C_Init */
/*
*==============================================================
* MMC ADDRESSING
*==============================================================
*/
/*! @brief Table holding all possible address values in IPMB specification
* @see get_ipmb_addr()
*/
unsigned char IPMBL_TABLE[IPMBL_TABLE_SIZE] = {
0x70, 0x8A, 0x72, 0x8E, 0x92, 0x90, 0x74, 0x8C, 0x76,
0x98, 0x9C, 0x9A, 0xA0, 0xA4, 0x88, 0x9E, 0x86, 0x84,
0x78, 0x94, 0x7A, 0x96, 0x82, 0x80, 0x7C, 0x7E, 0xA2 };
/*! The state of each GA signal is represented by G (grounded), U (unconnected),
* or P (pulled up to Management Power).
*
* The MMC drives P1 low and reads the GA lines. The MMC then drives P1 high and
* reads the GA lines. Any line that changes state between the two reads indicate
* an unconnected (U) pin.
*
* The IPMB-L address of a Module can be calculated as (70h + Site Number x 2). <br>
* G = 0, P = 1, U = 2 <br>
* | Pin | Ternary | Decimal | Address |
* |:---:|:-------:|:-------:|:-------:|
* | GGG | 000 | 0 | 0x70 |
* | GGP | 001 | 1 | 0x8A |
* | GGU | 002 | 2 | 0x72 |
* | GPG | 010 | 3 | 0x8E |
* | GPP | 011 | 4 | 0x92 |
* | GPU | 012 | 5 | 0x90 |
* | GUG | 020 | 6 | 0x74 |
* | GUP | 021 | 7 | 0x8C |
* | GUU | 022 | 8 | 0x76 |
* | PGG | 100 | 9 | 0x98 |
* | PGP | 101 | 10 | 0x9C |
* | PGU | 102 | 11 | 0x9A |
* | PPG | 110 | 12 | 0xA0 |
* | PPP | 111 | 13 | 0xA4 |
* | PPU | 112 | 14 | 0x88 |
* | PUG | 120 | 15 | 0x9E |
* | PUP | 121 | 16 | 0x86 |
* | PUU | 122 | 17 | 0x84 |
* | UGG | 200 | 18 | 0x78 |
* | UGP | 201 | 19 | 0x94 |
* | UGU | 202 | 20 | 0x7A |
* | UPG | 210 | 21 | 0x96 |
* | UPP | 211 | 22 | 0x82 |
* | UPU | 212 | 23 | 0x80 |
* | UUG | 220 | 24 | 0x7C |
* | UUP | 221 | 25 | 0x7E |
* | UUU | 222 | 26 | 0xA2 |
*/
#define GPIO_GA_DELAY 10
uint8_t get_ipmb_addr( void )
{
uint8_t ga0, ga1, ga2;
uint8_t index;
/* Set the test pin and read all GA pins */
Chip_GPIO_SetPinState(LPC_GPIO, GA_TEST_PORT, GA_TEST_PIN, 1);
/* when using NAMC-EXT-RTM at least 11 instruction cycles required
* to have correct GA value after GA_TEST_PIN changes */
{
uint8_t i;
for (i = 0; i < GPIO_GA_DELAY; i++){
__asm volatile ("nop");
}
}
ga0 = Chip_GPIO_GetPinState(LPC_GPIO, GA0_PORT, GA0_PIN);
ga1 = Chip_GPIO_GetPinState(LPC_GPIO, GA1_PORT, GA1_PIN);
ga2 = Chip_GPIO_GetPinState(LPC_GPIO, GA2_PORT, GA2_PIN);
/* Clear the test pin and see if any GA pin has changed is value,
* meaning that it is unconnected */
Chip_GPIO_SetPinState(LPC_GPIO, GA_TEST_PORT, GA_TEST_PIN, 0);
/* when using NAMC-EXT-RTM at least 11 instruction cycles required
* to have correct GA value after GA_TEST_PIN changes */
{
uint8_t i;
for (i = 0; i < GPIO_GA_DELAY; i++)
__asm volatile ("nop");
}
if ( ga0 != Chip_GPIO_GetPinState(LPC_GPIO, GA0_PORT, GA0_PIN) ){
ga0 = UNCONNECTED;
}
if ( ga1 != Chip_GPIO_GetPinState(LPC_GPIO, GA1_PORT, GA1_PIN) ){
ga1 = UNCONNECTED;
}
if ( ga2 != Chip_GPIO_GetPinState(LPC_GPIO, GA2_PORT, GA2_PIN) ){
ga2 = UNCONNECTED;
}
/* Transform the 3-based code in a decimal number */
index = (9 * ga2) + (3 * ga1) + (1 * ga0);
if ( index >= IPMBL_TABLE_SIZE ){
return 0;
}
return IPMBL_TABLE[index];
}
#undef GPIO_GA_DELAY
/*
* AFCIPMI
*
* Copyright (C) 2015 Henrique Silva <henrique.silva@lnls.br>
*
* 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 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*!
* @file i2c.h
* @author Henrique Silva <henrique.silva@lnls.br>, LNLS
* @date August 2015
*
* @brief Definitions used in I2C Driver
*/
#ifndef I2C_H_
#define I2C_H_
#include "FreeRTOS.h"
#include "task.h"
/*! @brief Max message length (in bits) used in I2C */
#define i2cMAX_MSG_LENGTH 32
/*! @brief Size of #IPMBL_TABLE
*/
#define IPMBL_TABLE_SIZE 27
/*! @brief GA pins definition */
typedef enum {
GROUNDED = 0,
POWERED,
UNCONNECTED
}GA_Pin_state;
/*! @brief I2C Modes definition
* @warning Slave Transmit (Slave write) mode is not implemented
*/
typedef enum {
I2C_Mode_Local_Master = 0, /*!< <b>Master Write</b> and <b>Master Read</b> modes only */
I2C_Mode_IPMB /*!< <b>Master Write</b> and <b>Slave Read</b> modes only */
} I2C_Mode;
/*! @brief I2C driver error enumeration */
typedef enum {
i2c_err_SUCCESS = 0,
i2c_err_FAILURE, /*!< General Failure in I2C driver */
i2c_err_MAX_LENGTH, /*!< Message trying to be sent is higher than I2C buffer limit */
i2c_err_SLA_R_SENT_NACK, /*!< SLA+R address transmitted, but no response has been received.
* @see #I2C_STAT_SLA_R_SENT_NACK */
i2c_err_SLA_DATA_RECV_NACK, /*!< DATA byte has been received, NACK has been returned.
* This usually means that the master will only be reading one
* more byte from the slave.
* @see #I2C_STAT_DATA_RECV_NACK */
i2c_err_SLA_W_SENT_NACK, /*!< SLA+R address transmitted, but no response has been received.
* Slave is either busy or unreachable.
* @see #I2C_STAT_SLA_W_SENT_NACK */
i2c_err_DATA_SENT_NACK /*!< DATA byte has been transmitted, but NACK has returned.
* Slave is either busy or unreachable.
* @see #I2C_STAT_DATA_SENT_NACK */
} i2c_err;
/*! @brief I2C transaction parameter structure */
typedef struct xI2C_msg
{
uint8_t i2c_id; /*!< I2C interface number (0, 1 or 2) */
uint8_t addr; /*!< Slave address of I2C device */
uint8_t tx_data[i2cMAX_MSG_LENGTH]; /*!< Buffer cointaning bytes to transmit, limitted to #i2cMAX_MSG_LENGTH */
uint8_t tx_len; /*!< Number of bytes to transmit */
uint8_t rx_data[i2cMAX_MSG_LENGTH]; /*!< Buffer cointaning received bytes, limitted to #i2cMAX_MSG_LENGTH */
uint8_t rx_len; /*!< Number of bytes to receive */
i2c_err error; /*!< Error value from I2C driver
* @see #i2c_err
*/
} xI2C_msg;
extern uint8_t ipmb_addr;
/***********************/
/* Function Prototypes */
/***********************/
/*! @todo Update i2c function comments */
/*! @brief I2C Interface Initialization
*
* Initialize I2C corresponding pins with the following characteristics:
* - Open Drain
* - Function #3 (If I2C0, it's function #1)
* - No pull-up nor pull-down
*
* Configure and init the I2C interruption, with its priority set to one
* level below the maximum FreeRTOS priority, so the interruption service
* can access the API and manage the semaphore.
* @param i2c_id: Interface ID ( I2C0, I2C1, I2C2 )
* @param mode: Operating mode for the specified I2C interface
*/
void vI2CInit( uint8_t i2c_id, uint32_t speed, I2C_Mode mode );
/*! @todo Document this function */
//void vI2CConfig( I2C_ID_T id, uint32_t speed );
/*! @brief Enter Master Write mode and transmit a buffer
*
* Bytes are transmitted in crescent order, incrementing the buffer index.
*
* @note This function blocks until its completion, in other words, it'll only
* return when the whole buffer has been transmitted or an error occurs in I2C Driver.
*
* Example:
* @code
* uint8_t tx_buffer = { 0xAA, 0x55, 0x00, 0x01 };
* uint8_t slave_address = 0x72;
*
* if( xI2CWrite ( I2C1, slave_address, tx_buffer, sizeof(tx_buffer)/sizeof(tx_buffer[0])) == i2c_err_SUCCESS ) {
*
* // Send next message, for example
*
* } else {
*
* // Retry sending this message or handle error
*
* }
* @endcode
* @param i2c_id: Interface ID ( I2C0, I2C1, I2C2 ).
* @param addr: Destination of the message (7 bit address).
* @param tx_data: Pointer to buffer of bytes to be transmitted.
* @param tx_len: Length of tx_data buffer (must be lower than #i2cMAX_MSG_LENGTH, or an error will return)
* @return I2C Driver error
* @see #xI2CRead
* @see #xI2CSlaveTransfer
*/
//i2c_err xI2CMasterWrite( I2C_ID_T id, uint8_t addr, uint8_t * tx_buff, uint8_t tx_len );
/*! @brief Enter Master Read mode and receive a buffer from slave
*
* @note This function blocks until its completion, in other words, it'll only
* return when the whole buffer has been read or an error occurs in I2C Driver.
*
* @warning @p rx_data must be previously allocated to prevent invalid memory access by functions inside this routine.
*
* Example:
* @code
* uint8_t rx_data[i2cMAX_MSG_LENGTH];
* uint8_t slave_address = 0x72;
* uint8_t bytes_to_receive = 5;
*
* if( xI2CRead ( I2C1, slave_address, rx_data, bytes_to_receive)) == i2c_err_SUCCESS ) {
*
* //Read message and blink a LED
* if ( rx_data[1] == 0x0A ) {
* blink_led(green);
* } else {
* blink_led(red);
* }
*
* } else {
*
* // Retry sending this command or handle error
*
* }
* @endcode
* @param i2c_id: Interface ID ( I2C0, I2C1, I2C2 ).
* @param addr: Destination of the message (7 bit address).
* @param rx_data: Pointer to buffer in which the received bytes will be copied.
* @param rx_len: Number of bytes that will be read from slave
* @return I2C Driver error
* @see #xI2CWrite
* @see #xI2CSlaveTransfer
*/
//i2c_err xI2CMasterRead( I2C_ID_T id, uint8_t addr, uint8_t * rx_buff, uint8_t rx_len );
/*! @todo Document this function */
//i2c_err xI2CMasterWriteRead( I2C_ID_T id, uint8_t addr, uint8_t cmd, uint8_t * rx_buff, uint8_t rx_len );
/*! @brief Enter Slave Receiver mode and waits a data transmission
*
* This function forces the I2C interface switch to Slave Listen (Receiver) mode
* and waits another Master on the bus transmit any data.
* A timeout can be specified for this function, so your functions only block here
* as long as they want.
*
* @warning @p rx_data must be previously allocated to prevent invalid memory access by functions inside this routine.
*
* Example:
* @code
* uint8_t rx_data[i2cMAX_MSG_LENGTH];
* uint32_t timeout = 1000/portTICK_PERIOD_MS; // Specified in ticks ( you can convert to ms dividing the desired value by portTICK_PERIOD_MS macro, defined in portmacro.h file )
* uint8_t data_len;
*
* data_len = xI2CSlaveTransfer( I2C0, rx_data, timeout );
*
* //Read message and blink a LED
* if ( (data_len > 2) && (rx_data[1] == 0x0A) ) {
* blink_led(green);
* } else {
* blink_led(red);
* }
* @endcode
* @param i2c_id: Interface ID ( I2C0, I2C1, I2C2 ).
* @param rx_data: Pointer to buffer in which the received bytes will be copied.
* @param timeout: Amount of time to remain blocked until a message arrives (32-bit value)
* @return Length of message received
* @see #xI2CWrite
* @see #xI2CRead
*/
//uint8_t xI2CSlaveReceive( I2C_ID_T id, uint8_t * rx_buff, uint8_t buff_len, TickType_t timeout );
/*! @todo Document this function */
//void vI2CSlaveSetup ( I2C_ID_T id, uint8_t slave_addr );
/*! @brief Reads own I2C slave address using GA pins
*
* Based on coreipm/coreipm/mmc.c
* @author Gokhan Sozmen
* Reads the GA pins, performing an unconnection checking, to define the device I2C slave address, as specified by MicroTCA documentation.
*
* @return 7-bit Slave Address
*
* @todo Develop a function to discover the Geographic Address once (checking the GA pins)
* and store it into a global variable, since everytime a IPMI message is built
* (request or response) the MMC has to check its own address to fill the rs/rqSA field,
* and it takes some time to go through all this function.
*/
uint8_t get_ipmb_addr( void );
uint8_t ipmb_addr;
#endif /*I2C_H_*/
/* /*
* ipmb.c * openMMC -- Open Source modular IPM Controller firmware
* *
* AFCIPMI -- * Copyright (C) 2015-2016 Henrique Silva <henrique.silva@lnls.br>
*
* Copyright (C) 2015 Henrique Silva <henrique.silva@lnls.br>
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
...@@ -17,6 +15,8 @@ ...@@ -17,6 +15,8 @@
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* @license GPL-3.0+ <http://spdx.org/licenses/GPL-3.0+>
*/ */
/* FreeRTOS includes */ /* FreeRTOS includes */
...@@ -29,7 +29,7 @@ ...@@ -29,7 +29,7 @@
#include "string.h" #include "string.h"
/* Project includes */ /* Project includes */
#include "i2c.h" #include "utils.h"
#include "ipmb.h" #include "ipmb.h"
#include "ipmi.h" #include "ipmi.h"
#include "pin_mapping.h" #include "pin_mapping.h"
...@@ -44,9 +44,6 @@ ipmb_error ipmb_decode ( ipmi_msg * msg, uint8_t * buffer, uint8_t len ); ...@@ -44,9 +44,6 @@ ipmb_error ipmb_decode ( ipmi_msg * msg, uint8_t * buffer, uint8_t len );
#define I2C_SPEED 100000 #define I2C_SPEED 100000
/* Macro to check is the message is a response (odd netfn) */
#define IS_RESPONSE(msg) (msg.netfn & 0x01)
/* Local variables */ /* Local variables */
QueueHandle_t ipmb_txqueue = NULL; QueueHandle_t ipmb_txqueue = NULL;
QueueHandle_t client_queue = NULL; QueueHandle_t client_queue = NULL;
...@@ -66,7 +63,7 @@ void IPMB_TXTask ( void * pvParameters ) ...@@ -66,7 +63,7 @@ void IPMB_TXTask ( void * pvParameters )
/* We're sending a response */ /* We're sending a response */
/**********************************/ /**********************************/
/* Error checking */ /* Error checking */
/**********************************/ /**********************************/
/* See if we've already tried sending this message 3 times */ /* See if we've already tried sending this message 3 times */
...@@ -76,7 +73,7 @@ void IPMB_TXTask ( void * pvParameters ) ...@@ -76,7 +73,7 @@ void IPMB_TXTask ( void * pvParameters )
} }
/**********************************/ /**********************************/
/* Try sending the message */ /* Try sending the message */
/**********************************/ /**********************************/
/* Encode the message buffer to the IPMB format */ /* Encode the message buffer to the IPMB format */
...@@ -176,9 +173,13 @@ void IPMB_RXTask ( void *pvParameters ) ...@@ -176,9 +173,13 @@ void IPMB_RXTask ( void *pvParameters )
void ipmb_init ( void ) void ipmb_init ( void )
{ {
vI2CInit( IPMB_I2C, I2C_SPEED, I2C_Mode_IPMB ); vI2CConfig( IPMB_I2C, I2C_SPEED );
ipmb_addr = get_ipmb_addr( );
vI2CSlaveSetup( IPMB_I2C, ipmb_addr );
ipmb_txqueue = xQueueCreate( IPMB_TXQUEUE_LEN, sizeof(ipmi_msg_cfg) ); ipmb_txqueue = xQueueCreate( IPMB_TXQUEUE_LEN, sizeof(ipmi_msg_cfg) );
vQueueAddToRegistry( ipmb_txqueue, "IPMB_TX_QUEUE"); vQueueAddToRegistry( ipmb_txqueue, "IPMB_TX_QUEUE");
xTaskCreate( IPMB_TXTask, (const char*)"IPMB_TX", 150, ( void * ) NULL, tskIPMB_TX_PRIORITY, ( TaskHandle_t * ) NULL ); xTaskCreate( IPMB_TXTask, (const char*)"IPMB_TX", 150, ( void * ) NULL, tskIPMB_TX_PRIORITY, ( TaskHandle_t * ) NULL );
xTaskCreate( IPMB_RXTask, (const char*)"IPMB_RX", 300, ( void * ) NULL, tskIPMB_RX_PRIORITY, ( TaskHandle_t * ) NULL ); xTaskCreate( IPMB_RXTask, (const char*)"IPMB_RX", 300, ( void * ) NULL, tskIPMB_RX_PRIORITY, ( TaskHandle_t * ) NULL );
} }
...@@ -279,25 +280,6 @@ ipmb_error ipmb_register_rxqueue ( QueueHandle_t * queue ) ...@@ -279,25 +280,6 @@ ipmb_error ipmb_register_rxqueue ( QueueHandle_t * queue )
} }
} }
/*! @brief Calculate the IPMB message checksum byte.
* The cheksum byte is calculated by perfoming a simple 8bit 2's complement of the sum of all previous bytes.
* Since we're using a unsigned int to hold the checksum value, we only need to subtract all bytes from it.
* @param buffer Pointer to the message bytes.
* @param range How many bytes will be used in the calculation.
*
* @return Checksum of the specified bytes of the buffer.
*/
uint8_t ipmb_calculate_chksum ( uint8_t * buffer, uint8_t range )
{
configASSERT( buffer != NULL );
uint8_t chksum = 0;
uint8_t i;
for ( i = 0; i < range; i++ ) {
chksum -= buffer[i];
}
return chksum;
}
/*! @brief Asserts the input message checksums by comparing them with our calculated ones. /*! @brief Asserts the input message checksums by comparing them with our calculated ones.
* *
* @param buffer Pointer to the message bytes. * @param buffer Pointer to the message bytes.
...@@ -313,8 +295,8 @@ ipmb_error ipmb_assert_chksum ( uint8_t * buffer, uint8_t buffer_len ) ...@@ -313,8 +295,8 @@ ipmb_error ipmb_assert_chksum ( uint8_t * buffer, uint8_t buffer_len )
uint8_t header_chksum = buffer[2]; uint8_t header_chksum = buffer[2];
uint8_t msg_chksum = buffer[buffer_len-1]; uint8_t msg_chksum = buffer[buffer_len-1];
uint8_t calc_header_chksum = ipmb_calculate_chksum( buffer, IPMI_HEADER_CHECKSUM_POSITION ); uint8_t calc_header_chksum = calculate_chksum( buffer, IPMI_HEADER_CHECKSUM_POSITION );
uint8_t calc_msg_chksum = ipmb_calculate_chksum( buffer, buffer_len-1 ); uint8_t calc_msg_chksum = calculate_chksum( buffer, buffer_len-1 );
if ( header_chksum == calc_header_chksum ) { if ( header_chksum == calc_header_chksum ) {
if ( msg_chksum == calc_msg_chksum ) { if ( msg_chksum == calc_msg_chksum ) {
return ipmb_error_success; return ipmb_error_success;
...@@ -364,7 +346,7 @@ ipmb_error ipmb_encode ( uint8_t * buffer, ipmi_msg * msg ) ...@@ -364,7 +346,7 @@ ipmb_error ipmb_encode ( uint8_t * buffer, ipmi_msg * msg )
buffer[i++] = msg->dest_addr; buffer[i++] = msg->dest_addr;
buffer[i++] = ( ( ( msg->netfn << 2 ) & IPMB_NETFN_MASK ) | ( msg->dest_LUN & IPMB_DEST_LUN_MASK ) ); buffer[i++] = ( ( ( msg->netfn << 2 ) & IPMB_NETFN_MASK ) | ( msg->dest_LUN & IPMB_DEST_LUN_MASK ) );
buffer[i++] = ipmb_calculate_chksum( &buffer[0], IPMI_HEADER_CHECKSUM_POSITION ); buffer[i++] = calculate_chksum( &buffer[0], IPMI_HEADER_CHECKSUM_POSITION );
buffer[i++] = msg->src_addr; buffer[i++] = msg->src_addr;
buffer[i++] = ( ( ( msg->seq << 2 ) & IPMB_SEQ_MASK ) | ( msg->src_LUN & IPMB_SRC_LUN_MASK ) ); buffer[i++] = ( ( ( msg->seq << 2 ) & IPMB_SEQ_MASK ) | ( msg->src_LUN & IPMB_SRC_LUN_MASK ) );
buffer[i++] = msg->cmd; buffer[i++] = msg->cmd;
...@@ -373,7 +355,7 @@ ipmb_error ipmb_encode ( uint8_t * buffer, ipmi_msg * msg ) ...@@ -373,7 +355,7 @@ ipmb_error ipmb_encode ( uint8_t * buffer, ipmi_msg * msg )
} }
memcpy (&buffer[i], &msg->data[0], msg->data_len); memcpy (&buffer[i], &msg->data[0], msg->data_len);
i += msg->data_len; i += msg->data_len;
buffer[i] = ipmb_calculate_chksum( &buffer[0], i ); buffer[i] = calculate_chksum( &buffer[0], i );
return ipmb_error_success; return ipmb_error_success;
} }
...@@ -411,3 +393,116 @@ ipmb_error ipmb_decode ( ipmi_msg * msg, uint8_t * buffer, uint8_t len ) ...@@ -411,3 +393,116 @@ ipmb_error ipmb_decode ( ipmi_msg * msg, uint8_t * buffer, uint8_t len )
return ipmb_error_success; return ipmb_error_success;
} }
/*
*==============================================================
* MMC ADDRESSING
*==============================================================
*/
/*! @brief Table holding all possible address values in IPMB specification
* @see get_ipmb_addr()
*/
unsigned char IPMBL_TABLE[IPMBL_TABLE_SIZE] = {
0x70, 0x8A, 0x72, 0x8E, 0x92, 0x90, 0x74, 0x8C, 0x76,
0x98, 0x9C, 0x9A, 0xA0, 0xA4, 0x88, 0x9E, 0x86, 0x84,
0x78, 0x94, 0x7A, 0x96, 0x82, 0x80, 0x7C, 0x7E, 0xA2 };
/*! The state of each GA signal is represented by G (grounded), U (unconnected),
* or P (pulled up to Management Power).
*
* The MMC drives P1 low and reads the GA lines. The MMC then drives P1 high and
* reads the GA lines. Any line that changes state between the two reads indicate
* an unconnected (U) pin.
*
* The IPMB-L address of a Module can be calculated as (70h + Site Number x 2). <br>
* G = 0, P = 1, U = 2 <br>
* | Pin | Ternary | Decimal | Address |
* |:---:|:-------:|:-------:|:-------:|
* | GGG | 000 | 0 | 0x70 |
* | GGP | 001 | 1 | 0x8A |
* | GGU | 002 | 2 | 0x72 |
* | GPG | 010 | 3 | 0x8E |
* | GPP | 011 | 4 | 0x92 |
* | GPU | 012 | 5 | 0x90 |
* | GUG | 020 | 6 | 0x74 |
* | GUP | 021 | 7 | 0x8C |
* | GUU | 022 | 8 | 0x76 |
* | PGG | 100 | 9 | 0x98 |
* | PGP | 101 | 10 | 0x9C |
* | PGU | 102 | 11 | 0x9A |
* | PPG | 110 | 12 | 0xA0 |
* | PPP | 111 | 13 | 0xA4 |
* | PPU | 112 | 14 | 0x88 |
* | PUG | 120 | 15 | 0x9E |
* | PUP | 121 | 16 | 0x86 |
* | PUU | 122 | 17 | 0x84 |
* | UGG | 200 | 18 | 0x78 |
* | UGP | 201 | 19 | 0x94 |
* | UGU | 202 | 20 | 0x7A |
* | UPG | 210 | 21 | 0x96 |
* | UPP | 211 | 22 | 0x82 |
* | UPU | 212 | 23 | 0x80 |
* | UUG | 220 | 24 | 0x7C |
* | UUP | 221 | 25 | 0x7E |
* | UUU | 222 | 26 | 0xA2 |
*/
#define GPIO_GA_DELAY 10
uint8_t get_ipmb_addr( void )
{
uint8_t ga0, ga1, ga2;
uint8_t index;
/* Set the test pin and read all GA pins */
gpio_set_pin_dir(GA_TEST_PORT, GA_TEST_PIN, OUTPUT);
gpio_set_pin_state(GA_TEST_PORT, GA_TEST_PIN, HIGH);
/* when using NAMC-EXT-RTM at least 11 instruction cycles required
* to have correct GA value after GA_TEST_PIN changes */
{
uint8_t i;
for (i = 0; i < GPIO_GA_DELAY; i++){
__asm volatile ("nop");
}
}
ga0 = gpio_read_pin(GA0_PORT, GA0_PIN);
ga1 = gpio_read_pin(GA1_PORT, GA1_PIN);
ga2 = gpio_read_pin(GA2_PORT, GA2_PIN);
/* Clear the test pin and see if any GA pin has changed is value,
* meaning that it is unconnected */
gpio_set_pin_state(GA_TEST_PORT, GA_TEST_PIN, LOW);
/* when using NAMC-EXT-RTM at least 11 instruction cycles required
* to have correct GA value after GA_TEST_PIN changes */
{
uint8_t i;
for (i = 0; i < GPIO_GA_DELAY; i++)
__asm volatile ("nop");
}
if ( ga0 != gpio_read_pin(GA0_PORT, GA0_PIN) ){
ga0 = UNCONNECTED;
}
if ( ga1 != gpio_read_pin(GA1_PORT, GA1_PIN) ){
ga1 = UNCONNECTED;
}
if ( ga2 != gpio_read_pin(GA2_PORT, GA2_PIN) ){
ga2 = UNCONNECTED;
}
/* Transform the 3-based code in a decimal number */
index = (9 * ga2) + (3 * ga1) + (1 * ga0);
if ( index >= IPMBL_TABLE_SIZE ){
return 0;
}
return IPMBL_TABLE[index];
}
#undef GPIO_GA_DELAY
/* /*
* AFCIPMI -- * openMMC -- Open Source modular IPM Controller firmware
* *
* Copyright (C) 2015 Henrique Silva <henrique.silva@lnls.br> * Copyright (C) 2015-2016 Henrique Silva <henrique.silva@lnls.br>
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
...@@ -15,6 +15,8 @@ ...@@ -15,6 +15,8 @@
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* @license GPL-3.0+ <http://spdx.org/licenses/GPL-3.0+>
*/ */
/*! /*!
...@@ -87,7 +89,6 @@ ...@@ -87,7 +89,6 @@
*/ */
#define IPMB_RESP_HEADER_LENGTH 7 #define IPMB_RESP_HEADER_LENGTH 7
#define IPMB_NETFN_MASK 0xFC #define IPMB_NETFN_MASK 0xFC
#define IPMB_DEST_LUN_MASK 0x3 #define IPMB_DEST_LUN_MASK 0x3
#define IPMB_SEQ_MASK 0xFC #define IPMB_SEQ_MASK 0xFC
...@@ -96,6 +97,19 @@ ...@@ -96,6 +97,19 @@
/*! @brief MicroTCA's MCH slave address */ /*! @brief MicroTCA's MCH slave address */
#define MCH_ADDRESS 0x20 #define MCH_ADDRESS 0x20
/* @brief Macro to check is the message is a response (odd netfn) */
#define IS_RESPONSE(msg) (msg.netfn & 0x01)
/*! @brief Size of #IPMBL_TABLE
*/
#define IPMBL_TABLE_SIZE 27
/*! @brief GA pins definition */
typedef enum {
GROUNDED = 0,
POWERED,
UNCONNECTED
}GA_Pin_state;
/*! @brief IPMI message struct */ /*! @brief IPMI message struct */
typedef struct ipmi_msg { typedef struct ipmi_msg {
...@@ -141,6 +155,8 @@ typedef enum ipmb_error { ...@@ -141,6 +155,8 @@ typedef enum ipmb_error {
ipmb_error_queue_creation /*!< Client queue couldn't be created. Invalid pointer to handler was given */ ipmb_error_queue_creation /*!< Client queue couldn't be created. Invalid pointer to handler was given */
} ipmb_error; } ipmb_error;
extern uint8_t ipmb_addr;
/* Function Prototypes */ /* Function Prototypes */
/*! @brief IPMB Transmitter Task /*! @brief IPMB Transmitter Task
...@@ -201,6 +217,20 @@ ipmb_error ipmb_send_response ( ipmi_msg * req, ipmi_msg * resp ); ...@@ -201,6 +217,20 @@ ipmb_error ipmb_send_response ( ipmi_msg * req, ipmi_msg * resp );
ipmb_error ipmb_register_rxqueue ( QueueHandle_t * queue ); ipmb_error ipmb_register_rxqueue ( QueueHandle_t * queue );
ipmb_error ipmb_assert_chksum ( uint8_t * buffer, uint8_t buffer_len ); ipmb_error ipmb_assert_chksum ( uint8_t * buffer, uint8_t buffer_len );
uint8_t ipmb_calculate_chksum ( uint8_t * buffer, uint8_t range );
/*! @brief Reads own I2C slave address using GA pins
*
* Based on coreipm/coreipm/mmc.c
* @author Gokhan Sozmen
* Reads the GA pins, performing an unconnection checking, to define the device I2C slave address, as specified by MicroTCA documentation.
*
* @return 7-bit Slave Address
*
* @todo Develop a function to discover the Geographic Address once (checking the GA pins)
* and store it into a global variable, since everytime a IPMI message is built
* (request or response) the MMC has to check its own address to fill the rs/rqSA field,
* and it takes some time to go through all this function.
*/
uint8_t get_ipmb_addr( void );
#endif #endif
/* /*
* ipmi.c * openMMC -- Open Source modular IPM Controller firmware
* *
* AFCIPMI -- * Copyright (C) 2015-2016 Henrique Silva <henrique.silva@lnls.br>
*
* Copyright (C) 2015 Henrique Silva <henrique.silva@lnls.br>
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
...@@ -17,6 +15,8 @@ ...@@ -17,6 +15,8 @@
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* @license GPL-3.0+ <http://spdx.org/licenses/GPL-3.0+>
*/ */
/* C Standard includes */ /* C Standard includes */
...@@ -26,31 +26,27 @@ ...@@ -26,31 +26,27 @@
#include "FreeRTOS.h" #include "FreeRTOS.h"
#include "ipmi.h" #include "ipmi.h"
#include "pin_mapping.h" #include "pin_mapping.h"
#include "led.h"
#include "task_priorities.h" #include "task_priorities.h"
#include "led.h" #include "led.h"
#include "payload.h"
/* Local variables */ /* Local variables */
QueueHandle_t ipmi_rxqueue = NULL; QueueHandle_t ipmi_rxqueue = NULL;
struct req_param_struct{ volatile const t_req_handler_record *ipmiEntries = (t_req_handler_record *) &_ipmi_handlers;
ipmi_msg req_received; volatile const t_req_handler_record *ipmiEntries_end = (t_req_handler_record *) &_eipmi_handlers;
t_req_handler req_handler;
}; void IPMITask( void * pvParameters )
uint32_t handler_max_watermark = 0;
extern t_req_handler_record handlers[MAX_HANDLERS];
extern void ipmi_se_set_receiver ( ipmi_msg *req, ipmi_msg *rsp);
void IPMITask ( void * pvParameters )
{ {
ipmi_msg req_received; ipmi_msg req_received;
ipmi_msg response;
ipmb_error error_code;
t_req_handler req_handler = (t_req_handler) 0; t_req_handler req_handler = (t_req_handler) 0;
for ( ;; ){ for ( ;; ) {
/* Received request and handler function must be allocated
dynamically so they can be passed to the dynamically-created
handler tasks. These tasks must also free the memory after use */
if( xQueueReceive( ipmi_rxqueue, &req_received , portMAX_DELAY ) == pdFALSE){ if( xQueueReceive( ipmi_rxqueue, &req_received , portMAX_DELAY ) == pdFALSE) {
/* Should no return pdFALSE */
configASSERT(pdFALSE); configASSERT(pdFALSE);
continue; continue;
} }
...@@ -58,30 +54,23 @@ void IPMITask ( void * pvParameters ) ...@@ -58,30 +54,23 @@ void IPMITask ( void * pvParameters )
req_handler = (t_req_handler) 0; req_handler = (t_req_handler) 0;
req_handler = ipmi_retrieve_handler(req_received.netfn, req_received.cmd); req_handler = ipmi_retrieve_handler(req_received.netfn, req_received.cmd);
if (req_handler != 0){ if (req_handler != 0) {
/* TODO: create unique name for each created task, probably response.completion_code = IPMI_CC_UNSPECIFIED_ERROR;
related to netfn and command */ response.data_len = 0;
struct req_param_struct *req_param = pvPortMalloc(sizeof(struct req_param_struct));
/* Call user-defined function, give request data and retrieve required response */
if (req_param != NULL) { /* WARNING: Since IPMI task have a high priority, this handler function should not wait other tasks to unblock */
req_param->req_received = req_received; req_handler(&req_received, &response);
req_param->req_handler = req_handler;
} else { error_code = ipmb_send_response(&req_received, &response);
/* TODO: handle this problem */
} /* In case of error during IPMB response, the MMC may wait for a
new command from the MCH. Check this for debugging purposes
while ( xTaskCreate(IPMI_handler_task ,(const char*)"IPMI_handler_task", 80, req_param, tskIPMI_HANDLERS_PRIORITY, (TaskHandle_t *) NULL ) != pdTRUE ){ only. */
/* If the task couldn't be created, most likely we're out of heap, enter blocked state so that Idle task can run and free up some memory for us */ configASSERT( (error_code == ipmb_error_success) );
LED_update(LED_RED, &LED_On_Activity);
vTaskDelay(5); } else {
/* TODO: handle this problem */
}
LED_update(LED_RED, &LED_Off_Activity);
}else{
ipmb_error error_code;
ipmi_msg response;
/* If there is no function handler, use data from received /* If there is no function handler, use data from received
message to send "invalid command" response (IPMI table 5-2, message to send "invalid command" response (IPMI table 5-2,
page 44). */ page 44). */
...@@ -95,46 +84,6 @@ void IPMITask ( void * pvParameters ) ...@@ -95,46 +84,6 @@ void IPMITask ( void * pvParameters )
} }
} }
/*!
* This task is created dynamically each time there is an IPMI request
* demanding response. It receives a pointer to a struct contaning
* both the function handler and the request to treated, and must free
* this struct memory and itself before finishing.
*
* @param pvParameters pointer to req_param_struct contaning
* req_handler and req_received. This is dynamically allocated memory
* and should be freed before quitting.
*/
void IPMI_handler_task( void * pvParameters){
struct req_param_struct * req_param = (struct req_param_struct *) pvParameters;
ipmi_msg response;
ipmb_error response_error;
response.completion_code = IPMI_CC_UNSPECIFIED_ERROR;
response.data_len = 0;
/* Call user-defined function, give request data and retrieve required response */
req_param->req_handler(&(req_param->req_received), &response);
response_error = ipmb_send_response(&(req_param->req_received), &response);
/* In case of error during IPMB response, the MMC may wait for a
new command from the MCH. Check this for debugging purposes
only. */
configASSERT( response_error == ipmb_error_success );
/* Check how deep the handler task went in the stack */
uint32_t watermark = uxTaskGetStackHighWaterMark(NULL);
if (watermark > handler_max_watermark) {
handler_max_watermark = watermark;
}
vPortFree(req_param);
vTaskDelete(NULL);
}
/* Initializes the IPMI Dispatcher: /* Initializes the IPMI Dispatcher:
* -> Initializes the IPMB Layer * -> Initializes the IPMB Layer
* -> Registers the RX queue for incoming requests * -> Registers the RX queue for incoming requests
...@@ -149,7 +98,6 @@ void ipmi_init ( void ) ...@@ -149,7 +98,6 @@ void ipmi_init ( void )
xTaskCreate( IPMITask, (const char*)"IPMI Dispatcher", configMINIMAL_STACK_SIZE*2, ( void * ) NULL, tskIPMI_PRIORITY, &TaskIPMI_Handle ); xTaskCreate( IPMITask, (const char*)"IPMI Dispatcher", configMINIMAL_STACK_SIZE*2, ( void * ) NULL, tskIPMI_PRIORITY, &TaskIPMI_Handle );
} }
/*! /*!
* @brief Finds a handler associated with a given netfunction and command. * @brief Finds a handler associated with a given netfunction and command.
* *
...@@ -158,24 +106,46 @@ void ipmi_init ( void ) ...@@ -158,24 +106,46 @@ void ipmi_init ( void )
* *
* @return Pointer to the function which will handle this command, as defined in the netfn handler list. * @return Pointer to the function which will handle this command, as defined in the netfn handler list.
*/ */
t_req_handler ipmi_retrieve_handler(uint8_t netfn, uint8_t cmd){ t_req_handler ipmi_retrieve_handler(uint8_t netfn, uint8_t cmd)
uint8_t cur_handler; {
t_req_handler handler = 0; t_req_handler handler = 0;
t_req_handler_record * p_ptr = (t_req_handler_record *) ipmiEntries;
for(cur_handler = 0; cur_handler < MAX_HANDLERS; cur_handler++) while (p_ptr < ipmiEntries_end) {
{ if( (p_ptr->netfn == netfn) && \
(p_ptr->cmd == cmd)) {
if( (handlers[cur_handler].netfn == netfn) && \ handler = p_ptr->req_handler;
(handlers[cur_handler].cmd == cmd))
{
handler = handlers[cur_handler].req_handler;
break; break;
} }
p_ptr++;
} }
return handler; return handler;
} }
ipmb_error ipmi_event_send( sensor_t * sensor, uint8_t assert_deassert, uint8_t *evData, uint8_t length)
{
ipmi_msg evt;
uint8_t data_len = 0;
evt.dest_LUN = 0;
evt.netfn = NETFN_SE;
evt.cmd = IPMI_PLATFORM_EVENT_CMD;
evt.data[data_len++] = IPMI_EVENT_MESSAGE_REV;
evt.data[data_len++] = GET_SENSOR_TYPE(sensor);
evt.data[data_len++] = sensor->num;
evt.data[data_len++] = assert_deassert | (GET_EVENT_TYPE_CODE(sensor) & 0x7F);
evt.data[data_len++] = (length >= 1)? evData[0] : 0xFF;
evt.data[data_len++] = (length >= 2)? evData[1] : 0xFF;
evt.data[data_len++] = (length >= 3)? evData[2] : 0xFF;
evt.data_len = data_len;
return (ipmb_send_request( &evt ));
}
/*! /*!
* @brief Handler for GET Device ID command as in IPMI v2.0 section 20.1 for * @brief Handler for GET Device ID command as in IPMI v2.0 section 20.1 for
* more information. * more information.
...@@ -186,7 +156,8 @@ t_req_handler ipmi_retrieve_handler(uint8_t netfn, uint8_t cmd){ ...@@ -186,7 +156,8 @@ t_req_handler ipmi_retrieve_handler(uint8_t netfn, uint8_t cmd){
* *
* @return * @return
*/ */
void ipmi_app_get_device_id ( ipmi_msg *req, ipmi_msg * rsp ){ IPMI_HANDLER(ipmi_get_device_id, NETFN_APP, IPMI_GET_DEVICE_ID_CMD, ipmi_msg *req, ipmi_msg* rsp)
{
int len = rsp->data_len = 0; int len = rsp->data_len = 0;
rsp->completion_code = IPMI_CC_OK; rsp->completion_code = IPMI_CC_OK;
...@@ -199,7 +170,7 @@ void ipmi_app_get_device_id ( ipmi_msg *req, ipmi_msg * rsp ){ ...@@ -199,7 +170,7 @@ void ipmi_app_get_device_id ( ipmi_msg *req, ipmi_msg * rsp ){
rsp->data[len++] = 0x05; /* Dev FW Rev UPPER */ rsp->data[len++] = 0x05; /* Dev FW Rev UPPER */
rsp->data[len++] = 0x50; /* Dev FW Rev LOWER */ rsp->data[len++] = 0x50; /* Dev FW Rev LOWER */
rsp->data[len++] = 0x02; /* IPMI Version 2.0 */ rsp->data[len++] = 0x02; /* IPMI Version 2.0 */
rsp->data[len++] = 0x1F; /* Dev Support */ rsp->data[len++] = 0x3B; /* Dev Support */
rsp->data[len++] = 0x5A; /* Manufacturer ID LSB */ rsp->data[len++] = 0x5A; /* Manufacturer ID LSB */
rsp->data[len++] = 0x31; /* Manufacturer ID MSB */ rsp->data[len++] = 0x31; /* Manufacturer ID MSB */
rsp->data[len++] = 0x00; /* ID MSB */ rsp->data[len++] = 0x00; /* ID MSB */
...@@ -207,7 +178,27 @@ void ipmi_app_get_device_id ( ipmi_msg *req, ipmi_msg * rsp ){ ...@@ -207,7 +178,27 @@ void ipmi_app_get_device_id ( ipmi_msg *req, ipmi_msg * rsp ){
rsp->data[len++] = 0x01; /* Product ID MSB */ rsp->data[len++] = 0x01; /* Product ID MSB */
rsp->data_len = len; rsp->data_len = len;
}
/*!
* @brief Handler for GET Device GUID command
*
* @param req pointer to request message
*
* @param rsp pointer to response message
*
* @return
*/
IPMI_HANDLER(ipmi_get_device_guid, NETFN_APP, IPMI_GET_DEVICE_GUID_CMD, ipmi_msg *req, ipmi_msg* rsp)
{
int len = rsp->data_len = 0;
rsp->completion_code = IPMI_CC_OK;
/* TODO: Generate GUID - Globally Unique ID */
memset( &rsp->data[len], 0x00, 16);
rsp->data_len = 16;
} }
/*! /*!
...@@ -220,106 +211,35 @@ void ipmi_app_get_device_id ( ipmi_msg *req, ipmi_msg * rsp ){ ...@@ -220,106 +211,35 @@ void ipmi_app_get_device_id ( ipmi_msg *req, ipmi_msg * rsp ){
* *
* @return ipmi_msg Message with data, data length and completion code. * @return ipmi_msg Message with data, data length and completion code.
*/ */
void ipmi_picmg_get_properties ( ipmi_msg *req, ipmi_msg *rsp ) IPMI_HANDLER(ipmi_picmg_get_properties, NETFN_GRPEXT,IPMI_PICMG_CMD_GET_PROPERTIES, ipmi_msg *req, ipmi_msg *rsp )
{ {
int len = rsp->data_len = 0; int len = rsp->data_len = 0;
rsp->completion_code = IPMI_CC_OK; rsp->completion_code = IPMI_CC_OK;
/* Hardcoded response according to the */
rsp->data[len++] = IPMI_PICMG_GRP_EXT; rsp->data[len++] = IPMI_PICMG_GRP_EXT;
rsp->data[len++] = IPMI_EXTENSION_VERSION; rsp->data[len++] = IPMI_EXTENSION_VERSION;
/* MMCs must report MAX_FRU_ID and FRU_DEVICE_ID both as 0 - AMC.0 Table 3-1 */
rsp->data[len++] = MAX_FRU_ID; rsp->data[len++] = MAX_FRU_ID;
rsp->data[len++] = FRU_DEVICE_ID; rsp->data[len++] = FRU_DEVICE_ID;
rsp->data_len = len; rsp->data_len = len;
} }
IPMI_HANDLER(ipmi_picmg_cmd_set_amc_port_state, NETFN_GRPEXT, IPMI_PICMG_CMD_SET_AMC_PORT_STATE, ipmi_msg *req, ipmi_msg *rsp)
/*!
* @brief Handler for "Set FRU LED State"" request. Check IPMI 2.0
* table 3-31 for more information.
*
* @param[in] req Pointer to request struct to be handled and answered. Contains
* which LED should be set, how it should be set and other commands.
*
* @param[out] rsp Pointer to response struct to be modified with the message
*
* @return void
*/
#include "led.h"
void ipmi_picmg_set_led ( ipmi_msg *req, ipmi_msg *rsp )
{
led_error error;
const LED_activity_desc_t * pLEDact;
LED_activity_desc_t LEDact;
pLEDact = &LEDact;
/* We use this pointer assignment, so we can also set it to NULL if we need */
switch (req->data[3]) {
case 0x00:
/* OFF override */
pLEDact = &LED_Off_Activity;
break;
case 0xFF:
/* ON override */
pLEDact = &LED_On_Activity;
break;
case 0xFB:
/* Lamp Test */
/*! @todo Put the lamp test as a higher priority action, not a type of override */
LEDact.action = LED_ACTV_BLINK;
LEDact.initstate = LED_ON_STATE;
/* On duration in 100ms units */
LEDact.delay_init = req->data[4] * 100;
/* Set the toggle delay to 0, so we know its a "single-shot" descriptor, so the LED module should revert to its override/local_control state later */
LEDact.delay_tog = 0;
break;
case 0xFC:
/* Local state */
pLEDact = NULL;
break;
case 0xFD:
case 0xFE:
/* Reserved */
break;
default:
/* Blink Override */
LEDact.action = LED_ACTV_BLINK;
LEDact.initstate = LED_ON_STATE;
/* On duration in 10ms units */
LEDact.delay_init = req->data[4] / 10;
/* Off duration in 10ms units*/
LEDact.delay_tog = req->data[3] / 10;
break;
}
/* If this function does not block, we can't assure we have programmed the LED correctly, but if it does, there's the risk that this task won't kill itself and we'll run out of heap space */
error = LED_update( req->data[2], pLEDact );
switch (error) {
case led_success:
rsp->completion_code = IPMI_CC_OK;
break;
case led_invalid_argument:
rsp->completion_code = IPMI_CC_INV_DATA_FIELD_IN_REQ;
break;
case led_unspecified_error:
rsp->completion_code = IPMI_CC_UNSPECIFIED_ERROR;
break;
}
rsp->data_len = 0;
rsp->data[rsp->data_len++] = IPMI_PICMG_GRP_EXT;
}
void ipmi_picmg_set_amc_port( ipmi_msg *req, ipmi_msg *rsp)
{ {
rsp->completion_code = IPMI_CC_OK; rsp->completion_code = IPMI_CC_OK;
rsp->data[rsp->data_len++] = IPMI_PICMG_GRP_EXT; rsp->data[rsp->data_len++] = IPMI_PICMG_GRP_EXT;
} }
#include "payload.h" /* Compatibility with Vadatech */
void ipmi_picmg_fru_control( ipmi_msg *req, ipmi_msg *rsp) IPMI_HANDLER(ipmi_get_device_locator_record, NETFN_GRPEXT, IPMI_PICMG_CMD_GET_DEVICE_LOCATOR_RECORD, ipmi_msg * req, ipmi_msg * rsp )
{ {
payload_send_message(PAYLOAD_MESSAGE_QUIESCED); uint8_t len = rsp->data_len = 0;
rsp->data[len++] = IPMI_PICMG_GRP_EXT;
rsp->data[len++] = 0x00;
rsp->data[len++] = 0x00;
rsp->data_len = len;
rsp->completion_code = IPMI_CC_OK; rsp->completion_code = IPMI_CC_OK;
rsp->data[rsp->data_len++] = IPMI_PICMG_GRP_EXT;
} }
/* /*
* ipmi.h * openMMC -- Open Source modular IPM Controller firmware
* *
* AFCIPMI -- * Copyright (C) 2015-2016 Henrique Silva <henrique.silva@lnls.br>
*
* Copyright (C) 2015 Henrique Silva <henrique.silva@lnls.br>
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
...@@ -17,21 +15,22 @@ ...@@ -17,21 +15,22 @@
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* @license GPL-3.0+ <http://spdx.org/licenses/GPL-3.0+>
*/ */
#ifndef IPMI_H_ #ifndef IPMI_H_
#define IPMI_H_ #define IPMI_H_
#include "ipmb.h" #include "ipmb.h"
#include "sdr.h"
#define IPMI_MAX_DATA_LEN 24 #define IPMI_MAX_DATA_LEN 24
#define IPMI_EXTENSION_VERSION 0x23 #define IPMI_EXTENSION_VERSION 0x14
#define MAX_FRU_ID 0x01 #define MAX_FRU_ID 0x00
#define FRU_DEVICE_ID 0x00 #define FRU_DEVICE_ID 0x00
#define MAX_HANDLERS 20
/* Known NetFn codes (even request codes only) */ /* Known NetFn codes (even request codes only) */
#define NETFN_CHASSIS 0x00 #define NETFN_CHASSIS 0x00
#define NETFN_BRIDGE 0x02 #define NETFN_BRIDGE 0x02
...@@ -258,6 +257,20 @@ ...@@ -258,6 +257,20 @@
#define IPMI_PICMG_CMD_GET_SHELF_MANAGER_IP_ADDRESSES 0x21 #define IPMI_PICMG_CMD_GET_SHELF_MANAGER_IP_ADDRESSES 0x21
#define IPMI_PICMG_CMD_SHELF_POWER_ALLOCATION 0x22 #define IPMI_PICMG_CMD_SHELF_POWER_ALLOCATION 0x22
#define IPMI_PICMG_CMD_GET_TELCO_ALARM_CAPABILITY 0x29 #define IPMI_PICMG_CMD_GET_TELCO_ALARM_CAPABILITY 0x29
/* HPM Commands */
#define IPMI_PICMG_CMD_HPM_GET_UPGRADE_CAPABILITIES 0x2E
#define IPMI_PICMG_CMD_HPM_GET_COMPONENT_PROPERTIES 0x2F
#define IPMI_PICMG_CMD_HPM_ABORT_FIRMWARE_UPGRADE 0x30
#define IPMI_PICMG_CMD_HPM_INITIATE_UPGRADE_ACTION 0x31
#define IPMI_PICMG_CMD_HPM_UPLOAD_FIRMWARE_BLOCK 0x32
#define IPMI_PICMG_CMD_HPM_FINISH_FIRMWARE_UPLOAD 0x33
#define IPMI_PICMG_CMD_HPM_GET_UPGRADE_STATUS 0x34
#define IPMI_PICMG_CMD_HPM_ACTIVATE_FIRMWARE 0x35
#define IPMI_PICMG_CMD_HPM_QUERY_SELF_RESULTS 0x36
#define IPMI_PICMG_CMD_HPM_QUERY_ROLLBACK_STATUS 0x37
#define IPMI_PICMG_CMD_HPM_INITIATE_MANUAL_ROLLBACK 0x38
#define IPMI_EVENT_MESSAGE_REV 0x04
/* Completion Codes */ /* Completion Codes */
#define IPMI_CC_OK 0x00 #define IPMI_CC_OK 0x00
...@@ -284,6 +297,7 @@ ...@@ -284,6 +297,7 @@
#define IPMI_CC_INSUFFICIENT_PRIVILEGES 0xd4 #define IPMI_CC_INSUFFICIENT_PRIVILEGES 0xd4
#define IPMI_CC_NOT_SUPPORTED_PRESENT_STATE 0xd5 #define IPMI_CC_NOT_SUPPORTED_PRESENT_STATE 0xd5
#define IPMI_CC_ILLEGAL_COMMAND_DISABLED 0xd6 #define IPMI_CC_ILLEGAL_COMMAND_DISABLED 0xd6
#define IPMI_CC_COMMAND_IN_PROGRESS 0x80
#define IPMI_CC_UNSPECIFIED_ERROR 0xff #define IPMI_CC_UNSPECIFIED_ERROR 0xff
typedef void (* t_req_handler)(ipmi_msg * req, ipmi_msg * resp); typedef void (* t_req_handler)(ipmi_msg * req, ipmi_msg * resp);
...@@ -292,19 +306,33 @@ typedef struct{ ...@@ -292,19 +306,33 @@ typedef struct{
uint8_t netfn; uint8_t netfn;
uint8_t cmd; uint8_t cmd;
t_req_handler req_handler; t_req_handler req_handler;
}t_req_handler_record; } t_req_handler_record;
/*
* WARNING!!! Using IPMI_HANDLER_ALIAS and IPMI_HANDLER required to have .ipmi_handlers section in linker script
* .ipmi_handlers : ALIGN(4)
* {
* _ipmi_handlers = .;
* KEEP(*(.ipmi_handlers))
* _eipmi_handlers = .;
* } >FLASHAREA
*/
extern const t_req_handler_record *_ipmi_handlers;
extern const t_req_handler_record *_eipmi_handlers;
#define IPMI_HANDLER_ALIAS(handler_fn, netfn_id, cmd_id) \
const t_req_handler_record __attribute__ ((section (".ipmi_handlers"))) ipmi_handler_##netfn_id##__##cmd_id##_s = { .req_handler = handler_fn , .netfn = netfn_id, .cmd = cmd_id }
#define IPMI_HANDLER(name, netfn_id, cmd_id, args...) \
void ipmi_handler_##netfn_id##__##cmd_id##_f(args); \
const t_req_handler_record __attribute__ ((section (".ipmi_handlers"))) ipmi_handler_##netfn_id##__##cmd_id##_s = { .req_handler = ipmi_handler_##netfn_id##__##cmd_id##_f , .netfn = netfn_id, .cmd = cmd_id }; \
void ipmi_handler_##netfn_id##__##cmd_id##_f(args)
/* Function Prototypes */ /* Function Prototypes */
void IPMITask ( void *pvParameters ); void IPMITask ( void *pvParameters );
void ipmi_init ( void ); void ipmi_init ( void );
void IPMI_handler_task( void * pvParameters);
t_req_handler ipmi_retrieve_handler(uint8_t netfn, uint8_t cmd); t_req_handler ipmi_retrieve_handler(uint8_t netfn, uint8_t cmd);
ipmb_error ipmi_event_send( sensor_t * sensor, uint8_t assert_deassert, uint8_t *evData, uint8_t length);
/* Handler functions */
void ipmi_app_get_device_id ( ipmi_msg *req, ipmi_msg *rsp );
void ipmi_picmg_set_led ( ipmi_msg *req, ipmi_msg *rsp );
void ipmi_picmg_get_properties ( ipmi_msg *req, ipmi_msg *rsp );
#endif #endif
#include "ipmi.h"
#include "led.h"
#include "sdr.h"
#include "fru.h"
extern void ipmi_storage_get_fru_inventory( ipmi_msg *req, ipmi_msg *rsp );
extern void ipmi_storage_read_fru_data( ipmi_msg *req, ipmi_msg *rsp );
extern void ipmi_app_get_device_id ( ipmi_msg *req, ipmi_msg *rsp );
extern void ipmi_picmg_set_led ( ipmi_msg *req, ipmi_msg *rsp );
extern void ipmi_picmg_get_properties ( ipmi_msg *req, ipmi_msg *rsp );
extern void ipmi_picmg_set_amc_port ( ipmi_msg *req, ipmi_msg *rsp );
extern void ipmi_picmg_fru_control ( ipmi_msg *req, ipmi_msg *rsp );
extern void ipmi_se_get_sdr_info( ipmi_msg *req, ipmi_msg* rsp);
extern void ipmi_se_reserve_device_sdr( ipmi_msg *req, ipmi_msg* rsp);
extern void ipmi_se_get_sdr( ipmi_msg *req, ipmi_msg* rsp);
extern void ipmi_se_get_sensor_reading( ipmi_msg *req, ipmi_msg* rsp);
extern void ipmi_se_set_receiver ( ipmi_msg *req, ipmi_msg *rsp);
t_req_handler_record handlers[MAX_HANDLERS]={
{
.netfn = NETFN_GRPEXT,
.cmd = IPMI_PICMG_CMD_GET_PROPERTIES,
.req_handler = ipmi_picmg_get_properties
},
{
.netfn = NETFN_GRPEXT,
.cmd = IPMI_PICMG_CMD_SET_FRU_LED_STATE,
.req_handler = ipmi_picmg_set_led
},
{
.netfn = NETFN_GRPEXT,
.cmd = IPMI_PICMG_CMD_SET_AMC_PORT_STATE,
.req_handler = ipmi_picmg_set_amc_port
},
{
.netfn = NETFN_GRPEXT,
.cmd = IPMI_PICMG_CMD_FRU_CONTROL,
.req_handler = ipmi_picmg_fru_control
},
{
.netfn = NETFN_SE,
.cmd = IPMI_GET_DEVICE_SDR_INFO_CMD,
.req_handler = ipmi_se_get_sdr_info
},
{
.netfn = NETFN_SE,
.cmd = IPMI_RESERVE_DEVICE_SDR_REPOSITORY_CMD,
.req_handler = ipmi_se_reserve_device_sdr
},
{
.netfn = NETFN_SE,
.cmd = IPMI_GET_DEVICE_SDR_CMD,
.req_handler = ipmi_se_get_sdr
},
{
.netfn = NETFN_SE,
.cmd = IPMI_GET_SENSOR_READING_CMD,
.req_handler = ipmi_se_get_sensor_reading
},
{
.netfn = NETFN_SE,
.cmd = IPMI_SET_EVENT_RECEIVER_CMD,
.req_handler = ipmi_se_set_receiver
},
{
.netfn = NETFN_APP,
.cmd = IPMI_GET_DEVICE_ID_CMD,
.req_handler = ipmi_app_get_device_id
},
{
.netfn = NETFN_STORAGE,
.cmd = IPMI_GET_FRU_INVENTORY_AREA_INFO_CMD,
.req_handler = ipmi_storage_get_fru_inventory
},
{
.netfn = NETFN_STORAGE,
.cmd = IPMI_READ_FRU_DATA_CMD,
.req_handler = ipmi_storage_read_fru_data
}
};
#ifndef JTAG_H_
#define JTAG_H_
#define SCANSTA_PORT 2
#define SCANSTA_ADDR0_PIN 0
#define SCANSTA_ADDR1_PIN 1
#define SCANSTA_ADDR2_PIN 2
#define SCANSTA_ADDR3_PIN 3
#define SCANSTA_ADDR4_PIN 4
#define SCANSTA_ADDR5_PIN 5
#define SCANSTA_ADDR6_PIN 6
#define SCANSTA_RST_PIN 7
void init_scansta( void );
#endif
/* /*
* AFCIPMI -- * openMMC -- Open Source modular IPM Controller firmware
* *
* Copyright (C) 2015 Henrique Silva <henrique.silva@lnls.br> * Copyright (C) 2015-2016 Henrique Silva <henrique.silva@lnls.br>
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
...@@ -15,6 +15,8 @@ ...@@ -15,6 +15,8 @@
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* @license GPL-3.0+ <http://spdx.org/licenses/GPL-3.0+>
*/ */
/*! /*!
...@@ -43,16 +45,6 @@ ...@@ -43,16 +45,6 @@
#include "pin_mapping.h" #include "pin_mapping.h"
#include "task_priorities.h" #include "task_priorities.h"
typedef struct {
LED_activity_desc_t cur_cfg;
LED_activity_desc_t last_cfg;
LED_activity_desc_t const * local_ptr;
uint32_t counter;
uint8_t Color;
LEDPincfg_t pin_cfg;
QueueHandle_t queue;
} LED_state_rec_t;
//extern LED_state_rec_t LEDstate[LED_CNT]; //extern LED_state_rec_t LEDstate[LED_CNT];
const LED_activity_desc_t LED_Off_Activity = {LED_ACTV_OFF, LED_OFF_STATE, 0, 0}; const LED_activity_desc_t LED_Off_Activity = {LED_ACTV_OFF, LED_OFF_STATE, 0, 0};
...@@ -63,7 +55,7 @@ const LED_activity_desc_t LED_2Hz_Blink_Activity = {LED_ACTV_BLINK, LED_ON_STATE ...@@ -63,7 +55,7 @@ const LED_activity_desc_t LED_2Hz_Blink_Activity = {LED_ACTV_BLINK, LED_ON_STATE
const LED_activity_desc_t LED_3sec_Lamp_Test_Activity = {LED_ACTV_BLINK, LED_ON_STATE, 30, 0}; const LED_activity_desc_t LED_3sec_Lamp_Test_Activity = {LED_ACTV_BLINK, LED_ON_STATE, 30, 0};
LED_state_rec_t LEDstate[LED_CNT] = { LED_state_rec_t LEDstate[LED_CNT] = {
{ [LED_BLUE] = {
.local_ptr = &LED_On_Activity, .local_ptr = &LED_On_Activity,
.counter = 0, .counter = 0,
.Color = LEDCOLOR_BLUE, .Color = LEDCOLOR_BLUE,
...@@ -74,27 +66,27 @@ LED_state_rec_t LEDstate[LED_CNT] = { ...@@ -74,27 +66,27 @@ LED_state_rec_t LEDstate[LED_CNT] = {
} }
}, },
{ [LED_GREEN] = {
.local_ptr = &LED_2Hz_Blink_Activity, .local_ptr = &LED_2Hz_Blink_Activity,
.Color = LEDCOLOR_GREEN, .Color = LEDCOLOR_GREEN,
.counter = 0, .counter = 0,
.pin_cfg = { .pin_cfg = {
.pin = LEDGREEN_PIN, .pin = LEDGREEN_PIN,
.port = LEDGREEN_PORT, .port = LEDGREEN_PORT,
.func = LED_PIN_FUNC .func = LED_PIN_FUNC
} }
}, },
{ [LED_RED] = {
.local_ptr = &LED_Off_Activity, .local_ptr = &LED_Off_Activity,
.Color = LEDCOLOR_RED, .Color = LEDCOLOR_RED,
.counter = 0, .counter = 0,
.pin_cfg = { .pin_cfg = {
.pin = LEDRED_PIN, .pin = LEDRED_PIN,
.port = LEDRED_PORT, .port = LEDRED_PORT,
.func = LED_PIN_FUNC .func = LED_PIN_FUNC
} }
} }
}; };
...@@ -109,7 +101,7 @@ void LEDTask( void * Parameters ) ...@@ -109,7 +101,7 @@ void LEDTask( void * Parameters )
LED_activity_desc_t new_cfg; LED_activity_desc_t new_cfg;
LED_state_rec_t* pLED; LED_state_rec_t* pLED;
uint8_t led_id; uint8_t led_id;
/* Task will run every 100ms */ /* Task will run every 50ms */
TickType_t xFrequency = 100 / portTICK_PERIOD_MS; TickType_t xFrequency = 100 / portTICK_PERIOD_MS;
TickType_t xLastWakeTime; TickType_t xLastWakeTime;
...@@ -123,11 +115,11 @@ void LEDTask( void * Parameters ) ...@@ -123,11 +115,11 @@ void LEDTask( void * Parameters )
if (cycle == 0) { if (cycle == 0) {
if (xQueueReceive( pLED->queue, &new_cfg, 0 ) == pdTRUE) { if (xQueueReceive( pLED->queue, &new_cfg, 0 ) == pdTRUE) {
/* Save the last config */ /* Save the last config */
memcpy(&(pLED->last_cfg), &(pLED->cur_cfg), sizeof(LED_activity_desc_t)); memcpy(&(pLED->last_cfg), &(pLED->cur_cfg), sizeof(LED_activity_desc_t));
/* Update the config struct */ /* Update the config struct */
memcpy(&(pLED->cur_cfg), &new_cfg, sizeof(LED_activity_desc_t)); memcpy(&(pLED->cur_cfg), &new_cfg, sizeof(LED_activity_desc_t));
LED_set_state(pLED->pin_cfg, pLED->cur_cfg.initstate); LED_set_state(pLED->pin_cfg, pLED->cur_cfg.initstate);
pLED->counter = pLED->cur_cfg.delay_init; pLED->counter = pLED->cur_cfg.delay_init;
} }
} }
...@@ -159,8 +151,7 @@ void LEDTask( void * Parameters ) ...@@ -159,8 +151,7 @@ void LEDTask( void * Parameters )
* Revert the LED to the last know state and stay in toggled state until next cycle * Revert the LED to the last know state and stay in toggled state until next cycle
*/ */
pLED->counter = cycle; pLED->counter = cycle;
memcpy(&(pLED->cur_cfg), &(pLED->last_cfg), sizeof(LED_activity_desc_t)); memcpy(&(pLED->cur_cfg), &(pLED->last_cfg), sizeof(LED_activity_desc_t));
//pLED->cur_cfg = pLED->last_cfg;
} }
} else { } else {
(pLED->counter)--; (pLED->counter)--;
...@@ -175,18 +166,25 @@ void LEDTask( void * Parameters ) ...@@ -175,18 +166,25 @@ void LEDTask( void * Parameters )
cycle--; cycle--;
} }
vTaskDelayUntil( &xLastWakeTime, xFrequency ); vTaskDelayUntil( &xLastWakeTime, xFrequency );
//vTaskDelay(90);
} }
} }
void LED_init(void) void LED_init(void)
{ {
/* Init LED Pin */
gpio_init();
/* Set pins as output */
gpio_set_pin_dir( LEDBLUE_PORT, LEDBLUE_PIN, OUTPUT);
gpio_set_pin_dir( LEDGREEN_PORT, LEDGREEN_PIN, OUTPUT);
gpio_set_pin_dir( LEDRED_PORT, LEDRED_PIN, OUTPUT);
LED_state_rec_t* pLED; LED_state_rec_t* pLED;
for (int i = 0; i<LED_CNT; i++){ for (int i = 0; i<LED_CNT; i++){
pLED = &LEDstate[i]; pLED = &LEDstate[i];
pLED->queue = xQueueCreate( 2, sizeof(LED_activity_desc_t)); pLED->queue = xQueueCreate( 2, sizeof(LED_activity_desc_t));
xQueueSend( pLED->queue, pLED->local_ptr, 0 ); xQueueSend( pLED->queue, pLED->local_ptr, 0 );
} }
xTaskCreate( LEDTask, (const char *) "LED Task", 120, (void * ) NULL, tskLED_PRIORITY, ( TaskHandle_t * ) NULL); xTaskCreate( LEDTask, (const char *) "LED Task", 120, (void * ) NULL, tskLED_PRIORITY, ( TaskHandle_t * ) NULL);
...@@ -218,14 +216,170 @@ led_error LED_update( uint8_t led_num, const LED_activity_desc_t * pLEDact ) ...@@ -218,14 +216,170 @@ led_error LED_update( uint8_t led_num, const LED_activity_desc_t * pLEDact )
if (pLEDact == NULL) { if (pLEDact == NULL) {
/* Update the local control pointer/prescaler */ /* Update the local control pointer/prescaler */
new_cfg = *(pLED->local_ptr); new_cfg = *(pLED->local_ptr);
} else { } else {
new_cfg = *(pLEDact); new_cfg = *(pLEDact);
} }
/* Send the new config to the LED Task */ /* Send the new config to the LED Task */
if (xQueueSend(pLED->queue, &new_cfg, 0) != pdTRUE) { if (xQueueSend(pLED->queue, &new_cfg, 0) != pdTRUE) {
/* TODO: Handle error */ /* TODO: Handle error */
} }
} }
return led_success; return led_success;
} }
/*!
* @brief Handler for "Set FRU LED State"" request. Check IPMI 2.0
* table 3-31 for more information.
*
* @param[in] req Pointer to request struct to be handled and answered. Contains
* which LED should be set, how it should be set and other commands.
*
* @param[out] rsp Pointer to response struct to be modified with the message
*
* @return void
*/
IPMI_HANDLER(ipmi_picmg_set_fru_led_state, NETFN_GRPEXT, IPMI_PICMG_CMD_SET_FRU_LED_STATE, ipmi_msg *req, ipmi_msg *rsp )
{
led_error error;
const LED_activity_desc_t * pLEDact;
LED_activity_desc_t LEDact;
pLEDact = &LEDact;
/* We use this pointer assignment, so we can also set it to NULL if we need */
switch (req->data[3]) {
case 0x00:
/* OFF override */
pLEDact = &LED_Off_Activity;
break;
case 0xFF:
/* ON override */
pLEDact = &LED_On_Activity;
break;
case 0xFB:
/* Lamp Test */
/*! @todo Put the lamp test as a higher priority action, not a type of override */
LEDact.action = LED_ACTV_BLINK;
LEDact.initstate = LED_ON_STATE;
/* On duration in 100ms units */
LEDact.delay_init = req->data[4] * 100;
/* Set the toggle delay to 0, so we know its a "single-shot" descriptor, so the LED module should revert to its override/local_control state later */
LEDact.delay_tog = 0;
break;
case 0xFC:
/* Local state */
pLEDact = NULL;
break;
case 0xFD:
case 0xFE:
/* Reserved */
break;
default:
/* Blink Override */
LEDact.action = LED_ACTV_BLINK;
LEDact.initstate = LED_ON_STATE;
/* On duration in 10ms units */
LEDact.delay_init = req->data[4] / 10;
/* Off duration in 10ms units*/
LEDact.delay_tog = req->data[3] / 10;
break;
}
error = LED_update( req->data[2], pLEDact );
switch (error) {
case led_success:
rsp->completion_code = IPMI_CC_OK;
break;
case led_invalid_argument:
rsp->completion_code = IPMI_CC_INV_DATA_FIELD_IN_REQ;
break;
case led_unspecified_error:
rsp->completion_code = IPMI_CC_UNSPECIFIED_ERROR;
break;
}
rsp->data_len = 0;
rsp->data[rsp->data_len++] = IPMI_PICMG_GRP_EXT;
}
IPMI_HANDLER(ipmi_picmg_get_fru_led_properties, NETFN_GRPEXT, IPMI_PICMG_CMD_GET_FRU_LED_PROPERTIES, ipmi_msg *req, ipmi_msg *rsp )
{
uint8_t len = rsp->data_len = 0;
rsp->data[len++] = IPMI_PICMG_GRP_EXT;
/* FRU can control the BLUE LED, LED 1 (RED) and LED 2 (GREEN) */
rsp->data[len++] = 0x03;
/* Application specific LED count */
rsp->data[len++] = 0x00;
rsp->data_len = len;
rsp->completion_code = IPMI_CC_OK;
}
IPMI_HANDLER(ipmi_picmg_get_fru_led_state, NETFN_GRPEXT, IPMI_PICMG_CMD_GET_FRU_LED_STATE, ipmi_msg *req, ipmi_msg *rsp )
{
uint8_t len = rsp->data_len = 0;
uint8_t led_id = req->data[2];
if (led_id > LED_CNT) {
rsp->data_len = len;
rsp->completion_code = IPMI_CC_INV_DATA_FIELD_IN_REQ;
return;
}
rsp->data[len++] = IPMI_PICMG_GRP_EXT;
/* LED State:
* [7:4] Reserved,
* [3] LED has an unmet hardware restriction,
* [2] Lamp Test enabled
* [2] Override state enabled
* [2] Local control enabled */
rsp->data[len++] = 0x01; // Reading not yet implemented
/* Local Control LED function */
switch (LEDstate[led_id].cur_cfg.action) {
case LED_ACTV_OFF:
rsp->data[len++] = 0x00;
rsp->data[len++] = 0x00;
break;
case LED_ACTV_ON:
rsp->data[len++] = 0xFF;
rsp->data[len++] = 0x00;
break;
case LED_ACTV_BLINK:
rsp->data[len++] = LEDstate[led_id].cur_cfg.delay_init;
rsp->data[len++] = LEDstate[led_id].cur_cfg.delay_tog;
break;
}
/* Local Control Color */
rsp->data[len++] = LEDstate[led_id].Color;
rsp->data_len = len;
rsp->completion_code = IPMI_CC_OK;
}
IPMI_HANDLER(ipmi_picmg_get_led_color_capabilities, NETFN_GRPEXT, IPMI_PICMG_CMD_GET_LED_COLOR_CAPABILITIES, ipmi_msg *req, ipmi_msg *rsp )
{
uint8_t len = rsp->data_len = 0;
uint8_t led_id = req->data[2];
rsp->data[len++] = IPMI_PICMG_GRP_EXT;
/* LED Color Capabilities */
rsp->data[len++] = LEDstate[led_id].Color;
/* Default LED Color in Local Control State */
rsp->data[len++] = LEDstate[led_id].Color;
/* Default LED Color in Override State */
rsp->data[len++] = LEDstate[led_id].Color;
/* LED Flags:
* [7:2] Reserved,
* [1] LED has a hardware restriction,
* [0] LED won't work without payload power */
rsp->data[len++] = 0x00;
rsp->data_len = len;
rsp->completion_code = IPMI_CC_OK;
}
/*
* openMMC -- Open Source modular IPM Controller firmware
*
* Copyright (C) 2015-2016 Henrique Silva <henrique.silva@lnls.br>
*
* 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 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* @license GPL-3.0+ <http://spdx.org/licenses/GPL-3.0+>
*/
#ifndef LED_H_ #ifndef LED_H_
#define LED_H_ #define LED_H_
/* LEDs Pin and port definitions */ #include "ipmi.h"
/* LEDs Pin and port definitions */
#define LED_OFF_STATE (1) #define LED_OFF_STATE (1)
#define LED_ON_STATE (0) #define LED_ON_STATE (0)
...@@ -42,6 +64,16 @@ typedef struct { ...@@ -42,6 +64,16 @@ typedef struct {
uint32_t delay_tog; // period in opposite state in 10ms units, 0=skip uint32_t delay_tog; // period in opposite state in 10ms units, 0=skip
} LED_activity_desc_t; } LED_activity_desc_t;
typedef struct {
LED_activity_desc_t cur_cfg;
LED_activity_desc_t last_cfg;
LED_activity_desc_t const * local_ptr;
uint32_t counter;
uint8_t Color;
LEDPincfg_t pin_cfg;
QueueHandle_t queue;
} LED_state_rec_t;
typedef enum { typedef enum {
led_success = 0, led_success = 0,
led_unspecified_error, led_unspecified_error,
...@@ -56,7 +88,7 @@ extern const LED_activity_desc_t LED_3sec_Lamp_Test_Activity; ...@@ -56,7 +88,7 @@ extern const LED_activity_desc_t LED_3sec_Lamp_Test_Activity;
#define LED_on(cfg) gpio_clr_pin(cfg.port, cfg.pin) #define LED_on(cfg) gpio_clr_pin(cfg.port, cfg.pin)
#define LED_off(cfg) gpio_set_pin(cfg.port, cfg.pin) #define LED_off(cfg) gpio_set_pin(cfg.port, cfg.pin)
#define LED_toggle(cfg) gpio_pin_toggle( cfg.port, cfg.pin ) #define LED_toggle(cfg) gpio_pin_toggle(cfg.port, cfg.pin)
#define LED_is_off(cfg) gpio_read_pin(cfg.port, cfg.pin) #define LED_is_off(cfg) gpio_read_pin(cfg.port, cfg.pin)
#define LED_is_on(cfg) !gpio_read_pin(cfg.port, cfg.pin) #define LED_is_on(cfg) !gpio_read_pin(cfg.port, cfg.pin)
#define LED_get_state(cfg) gpio_read_pin(cfg.port, cfg.pin) #define LED_get_state(cfg) gpio_read_pin(cfg.port, cfg.pin)
...@@ -64,5 +96,6 @@ extern const LED_activity_desc_t LED_3sec_Lamp_Test_Activity; ...@@ -64,5 +96,6 @@ extern const LED_activity_desc_t LED_3sec_Lamp_Test_Activity;
void LED_init(void); void LED_init(void);
led_error LED_update( uint8_t led_num, const LED_activity_desc_t * pLEDact ); led_error LED_update( uint8_t led_num, const LED_activity_desc_t * pLEDact );
void ipmi_picmg_set_led(ipmi_msg *req, ipmi_msg *rsp);
#endif /* LED_H_ */ #endif /* LED_H_ */
/* /*
* payload.c * openMMC -- Open Source modular IPM Controller firmware
* *
* AFCIPMI -- * Copyright (C) 2015 Piotr Miedzik <P.Miedzik@gsi.de>
* * Copyright (C) 2015-2016 Henrique Silva <henrique.silva@lnls.br>
* Copyright (C) 2015 Piotr Miedzik <P.Miedzik@gsi.de>
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
...@@ -17,6 +16,8 @@ ...@@ -17,6 +16,8 @@
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* @license GPL-3.0+ <http://spdx.org/licenses/GPL-3.0+>
*/ */
/* FreeRTOS Includes */ /* FreeRTOS Includes */
...@@ -25,16 +26,17 @@ ...@@ -25,16 +26,17 @@
#include "queue.h" #include "queue.h"
#include "semphr.h" #include "semphr.h"
/* Project Includes */
#include "port.h" #include "port.h"
#include "payload.h" #include "payload.h"
#include "sdr.h"
#include "board_version.h" #include "board_version.h"
#include "pin_mapping.h" #include "pin_mapping.h"
#include "ipmi.h" #include "ipmi.h"
#include "task_priorities.h" #include "task_priorities.h"
#include "adn4604.h" #include "adn4604.h"
#include "led.h"
#include "ad84xx.h" #include "ad84xx.h"
#include "hotswap.h"
#include "utils.h"
/* payload states /* payload states
* 0 - no power * 0 - no power
...@@ -66,13 +68,24 @@ ...@@ -66,13 +68,24 @@
* 255 - power fail * 255 - power fail
*/ */
static void reset_FPGA( void ) void EINT3_IRQHandler( void )
{ {
gpio_set_pin_state( 2, 9, false); static TickType_t last_time;
gpio_set_pin_state( 2, 9, true); TickType_t current_time = xTaskGetTickCountFromISR();
/* Simple debouncing routine */
/* If the last interruption happened in the last 200ms, this one is only a bounce, ignore it and wait for the next interruption */
if (getTickDifference(current_time, last_time) < DEBOUNCE_TIME) {
return;
}
gpio_clr_pin(GPIO_FPGA_RESET_PORT, GPIO_FPGA_RESET_PIN);
asm("NOP");
gpio_set_pin(GPIO_FPGA_RESET_PORT, GPIO_FPGA_RESET_PIN);
} }
void setDC_DC_ConvertersON(bool on) { void setDC_DC_ConvertersON( bool on )
{
bool _on = on; bool _on = on;
/* @todo: check vadj relationship */ /* @todo: check vadj relationship */
...@@ -80,11 +93,11 @@ void setDC_DC_ConvertersON(bool on) { ...@@ -80,11 +93,11 @@ void setDC_DC_ConvertersON(bool on) {
bool _on_fmc2 = false | on; bool _on_fmc2 = false | on;
gpio_set_pin_state( GPIO_EN_FMC1_PVADJ_PORT, GPIO_EN_FMC1_PVADJ_PIN, _on_fmc1); gpio_set_pin_state( GPIO_EN_FMC1_PVADJ_PORT, GPIO_EN_FMC1_PVADJ_PIN, _on_fmc1);
gpio_set_pin_state( GPIO_EM_FMC1_P12V_PORT, GPIO_EM_FMC1_P12V_PIN, _on_fmc1); //gpio_set_pin_state( GPIO_EN_FMC1_P12V_PORT, GPIO_EN_FMC1_P12V_PIN, _on_fmc1);
gpio_set_pin_state( GPIO_EN_FMC1_P3V3_PORT, GPIO_EN_FMC1_P3V3_PIN, _on_fmc1); gpio_set_pin_state( GPIO_EN_FMC1_P3V3_PORT, GPIO_EN_FMC1_P3V3_PIN, _on_fmc1);
gpio_set_pin_state( GPIO_EN_FMC2_PVADJ_PORT, GPIO_EN_FMC2_PVADJ_PIN, _on_fmc2); gpio_set_pin_state( GPIO_EN_FMC2_PVADJ_PORT, GPIO_EN_FMC2_PVADJ_PIN, _on_fmc2);
gpio_set_pin_state( GPIO_EM_FMC2_P12V_PORT, GPIO_EM_FMC2_P12V_PIN, _on_fmc2); gpio_set_pin_state( GPIO_EN_FMC2_P12V_PORT, GPIO_EN_FMC2_P12V_PIN, _on_fmc2);
gpio_set_pin_state( GPIO_EN_FMC2_P3V3_PORT, GPIO_EN_FMC2_P3V3_PIN, _on_fmc2); gpio_set_pin_state( GPIO_EN_FMC2_P3V3_PORT, GPIO_EN_FMC2_P3V3_PIN, _on_fmc2);
...@@ -95,36 +108,33 @@ void setDC_DC_ConvertersON(bool on) { ...@@ -95,36 +108,33 @@ void setDC_DC_ConvertersON(bool on) {
gpio_set_pin_state( GPIO_EN_P3V3_PORT, GPIO_EN_P3V3_PIN, _on); gpio_set_pin_state( GPIO_EN_P3V3_PORT, GPIO_EN_P3V3_PIN, _on);
} }
void initializeDCDC() { void initializeDCDC( void )
{
setDC_DC_ConvertersON(false); setDC_DC_ConvertersON(false);
gpio_set_pin_dir( GPIO_EN_P1V2_PORT, GPIO_EN_P1V2_PIN, OUTPUT); gpio_set_pin_dir( GPIO_EN_P1V2_PORT, GPIO_EN_P1V2_PIN, OUTPUT);
gpio_set_pin_dir( GPIO_EN_P1V8_PORT, GPIO_EN_P1V8_PIN, OUTPUT); gpio_set_pin_dir( GPIO_EN_P1V8_PORT, GPIO_EN_P1V8_PIN, OUTPUT);
gpio_set_pin_dir( GPIO_EN_FMC2_P3V3_PORT, GPIO_EN_FMC2_P3V3_PIN, OUTPUT); gpio_set_pin_dir( GPIO_EN_FMC2_P3V3_PORT, GPIO_EN_FMC2_P3V3_PIN, OUTPUT);
gpio_set_pin_dir( GPIO_EN_FMC2_PVADJ_PORT, GPIO_EN_FMC2_PVADJ_PIN, OUTPUT); gpio_set_pin_dir( GPIO_EN_FMC2_PVADJ_PORT, GPIO_EN_FMC2_PVADJ_PIN, OUTPUT);
gpio_set_pin_dir( GPIO_EM_FMC2_P12V_PORT, GPIO_EM_FMC2_P12V_PIN, OUTPUT); gpio_set_pin_dir( GPIO_EN_FMC2_P12V_PORT, GPIO_EN_FMC2_P12V_PIN, OUTPUT);
gpio_set_pin_dir( GPIO_EM_FMC1_P12V_PORT, GPIO_EM_FMC1_P12V_PIN, OUTPUT); gpio_set_pin_dir( GPIO_EN_FMC1_P12V_PORT, GPIO_EN_FMC1_P12V_PIN, OUTPUT);
gpio_set_pin_dir( GPIO_EN_FMC1_P3V3_PORT, GPIO_EN_FMC1_P3V3_PIN, OUTPUT); gpio_set_pin_dir( GPIO_EN_FMC1_P3V3_PORT, GPIO_EN_FMC1_P3V3_PIN, OUTPUT);
gpio_set_pin_dir( GPIO_EN_FMC1_PVADJ_PORT, GPIO_EN_FMC1_PVADJ_PIN, OUTPUT); gpio_set_pin_dir( GPIO_EN_FMC1_PVADJ_PORT, GPIO_EN_FMC1_PVADJ_PIN, OUTPUT);
gpio_set_pin_dir( GPIO_EN_P3V3_PORT, GPIO_EN_P3V3_PIN, OUTPUT); gpio_set_pin_dir( GPIO_EN_P3V3_PORT, GPIO_EN_P3V3_PIN, OUTPUT);
gpio_set_pin_dir( GPIO_EN_1V5_VTT_PORT, GPIO_EN_1V5_VTT_PIN, OUTPUT); gpio_set_pin_dir( GPIO_EN_1V5_VTT_PORT, GPIO_EN_1V5_VTT_PIN, OUTPUT);
gpio_set_pin_dir( GPIO_EN_P1V0_PORT, GPIO_EN_P1V0_PIN, OUTPUT); gpio_set_pin_dir( GPIO_EN_P1V0_PORT, GPIO_EN_P1V0_PIN, OUTPUT);
/* RTM TEST */
gpio_set_pin_dir( 1, 30, OUTPUT);
gpio_set_pin_dir( GPIO_PROGRAM_B_PORT, GPIO_PROGRAM_B_PIN, OUTPUT);
} }
QueueHandle_t queue_payload_handle = 0; QueueHandle_t queue_payload_handle = 0;
void payload_send_message(uint8_t msg){ void payload_send_message(uint8_t msg)
if (queue_payload_handle == 0) return; {
if (queue_payload_handle) {
xQueueSend(queue_payload_handle, &msg, (TickType_t) 0); xQueueSend(queue_payload_handle, &msg, (TickType_t) 0);
}
} }
TaskHandle_t vTaskPayload_Handle; TaskHandle_t vTaskPayload_Handle;
...@@ -136,29 +146,35 @@ void payload_init( void ) ...@@ -136,29 +146,35 @@ void payload_init( void )
initializeDCDC(); initializeDCDC();
#ifdef MODULE_DAC_AD84XX
/* Configure the PVADJ DAC */
dac_vadj_init(); dac_vadj_init();
dac_vadj_config( 0, 25); dac_vadj_config( 0, 25 );
dac_vadj_config( 1, 25); dac_vadj_config( 1, 25 );
#endif
if (afc_board_info.board_version == BOARD_VERSION_AFC_V3_1) {
/* Flash CS Mux */ /* Configure FPGA reset button interruption on front panel */
/* 0 = FPGA reads bitstream from Program memory Chip_IOCON_PinMux(LPC_IOCON, GPIO_FPGA_RESET_PORT, GPIO_FPGA_RESET_PIN, IOCON_MODE_INACT, IOCON_FUNC1);
* 1 = FPGA reads bitstream from User memory irq_set_priority( EINT2_IRQn, configMAX_SYSCALL_INTERRUPT_PRIORITY - 1);
*/ irq_enable( EINT2_IRQn );
gpio_set_pin_dir(0, 19, OUTPUT);
gpio_set_pin_state(0, 19, LOW); if (board_info.board_version == BOARD_VERSION_AFC_V3_1) {
/* Flash CS Mux */
/* Init_B */ /* 0 = FPGA reads bitstream from Program memory
/* TODO: Check Init_b pin for error on initialization, then use it as output control */ * 1 = FPGA reads bitstream from User memory
*/
gpio_set_pin_dir(0, 20, OUTPUT); gpio_set_pin_dir(0, 19, OUTPUT);
gpio_set_pin_state(0, 20, HIGH); gpio_set_pin_state(0, 19, LOW);
/* Init_B */
/* TODO: Check Init_b pin for error on initialization, then use it as output control */
gpio_set_pin_dir(0, 20, OUTPUT);
gpio_set_pin_state(0, 20, HIGH);
} }
/* Enable RTM */
gpio_set_pin_state( 1, 30, true);
} }
void vTaskPayload(void *pvParmeters) void vTaskPayload(void *pvParameters)
{ {
payload_state state = PAYLOAD_NO_POWER; payload_state state = PAYLOAD_NO_POWER;
payload_state new_state = PAYLOAD_STATE_NO_CHANGE; payload_state new_state = PAYLOAD_STATE_NO_CHANGE;
...@@ -168,19 +184,17 @@ void vTaskPayload(void *pvParmeters) ...@@ -168,19 +184,17 @@ void vTaskPayload(void *pvParmeters)
uint8_t FPGA_boot_DONE = 0; uint8_t FPGA_boot_DONE = 0;
uint8_t QUIESCED_req = 0; uint8_t QUIESCED_req = 0;
ipmi_msg pmsg;
int data_len = 0;
uint8_t current_message; uint8_t current_message;
TickType_t xLastWakeTime; TickType_t xLastWakeTime;
xLastWakeTime = xTaskGetTickCount(); xLastWakeTime = xTaskGetTickCount();
gpio_set_pin_state( GPIO_PROGRAM_B_PORT, GPIO_PROGRAM_B_PIN, true); gpio_set_pin_state( GPIO_PROGRAM_B_PORT, GPIO_PROGRAM_B_PIN, HIGH);
for ( ;; ) { for ( ;; ) {
/* Initialize one of the FMC's DCDC so we can measure when the Payload Power is present */ /* Initialize one of the FMC's DCDC so we can measure when the Payload Power is present */
gpio_set_pin_state( GPIO_EM_FMC1_P12V_PORT, GPIO_EM_FMC1_P12V_PIN, true); gpio_set_pin_state( GPIO_EN_FMC1_P12V_PORT, GPIO_EN_FMC1_P12V_PIN, HIGH);
new_state = state; new_state = state;
...@@ -202,6 +216,14 @@ void vTaskPayload(void *pvParmeters) ...@@ -202,6 +216,14 @@ void vTaskPayload(void *pvParmeters)
case PAYLOAD_MESSAGE_QUIESCED: case PAYLOAD_MESSAGE_QUIESCED:
QUIESCED_req = 1; QUIESCED_req = 1;
break; break;
case PAYLOAD_MESSAGE_COLD_RST:
state = PAYLOAD_SWITCHING_OFF;
break;
case PAYLOAD_MESSAGE_REBOOT:
gpio_clr_pin(GPIO_FPGA_RESET_PORT, GPIO_FPGA_RESET_PIN);
asm("NOP");
gpio_set_pin(GPIO_FPGA_RESET_PORT, GPIO_FPGA_RESET_PIN);
break;
} }
} }
...@@ -212,7 +234,7 @@ void vTaskPayload(void *pvParmeters) ...@@ -212,7 +234,7 @@ void vTaskPayload(void *pvParmeters)
case PAYLOAD_NO_POWER: case PAYLOAD_NO_POWER:
if (P12V_good == 1) { if (P12V_good == 1) {
new_state = PAYLOAD_SWITCHING_ON; new_state = PAYLOAD_SWITCHING_ON;
} }
QUIESCED_req = 0; QUIESCED_req = 0;
break; break;
...@@ -222,7 +244,9 @@ void vTaskPayload(void *pvParmeters) ...@@ -222,7 +244,9 @@ void vTaskPayload(void *pvParmeters)
break; break;
case PAYLOAD_POWER_GOOD_WAIT: case PAYLOAD_POWER_GOOD_WAIT:
if (QUIESCED_req) { hotswap_clear_mask_bit( HOTSWAP_BACKEND_PWR_SHUTDOWN_MASK );
hotswap_clear_mask_bit( HOTSWAP_BACKEND_PWR_FAILURE_MASK );
if (QUIESCED_req) {
new_state = PAYLOAD_SWITCHING_OFF; new_state = PAYLOAD_SWITCHING_OFF;
} else if (P1V0_good == 1) { } else if (P1V0_good == 1) {
new_state = PAYLOAD_STATE_FPGA_SETUP; new_state = PAYLOAD_STATE_FPGA_SETUP;
...@@ -230,47 +254,41 @@ void vTaskPayload(void *pvParmeters) ...@@ -230,47 +254,41 @@ void vTaskPayload(void *pvParmeters)
break; break;
case PAYLOAD_STATE_FPGA_SETUP: case PAYLOAD_STATE_FPGA_SETUP:
adn4604_setup(); #ifdef MODULE_CLOCK_SWITCH
new_state = PAYLOAD_FPGA_BOOTING; adn4604_setup();
#endif
new_state = PAYLOAD_FPGA_BOOTING;
break; break;
case PAYLOAD_FPGA_BOOTING: case PAYLOAD_FPGA_BOOTING:
if (QUIESCED_req == 1) { if (QUIESCED_req == 1 || P12V_good == 0) {
new_state = PAYLOAD_SWITCHING_OFF; new_state = PAYLOAD_SWITCHING_OFF;
} else if (FPGA_boot_DONE) { } else if (FPGA_boot_DONE) {
new_state = PAYLOAD_FPGA_WORKING; new_state = PAYLOAD_FPGA_WORKING;
} else if (P12V_good == 0) { }
QUIESCED_req = 0; break;
new_state = PAYLOAD_NO_POWER;
}
break;
case PAYLOAD_FPGA_WORKING: case PAYLOAD_FPGA_WORKING:
if (QUIESCED_req == 1) { if (QUIESCED_req == 1 || P12V_good == 0) {
new_state = PAYLOAD_SWITCHING_OFF; new_state = PAYLOAD_SWITCHING_OFF;
} else if (P12V_good == 0) {
QUIESCED_req = 0;
new_state = PAYLOAD_NO_POWER;
} }
break; break;
case PAYLOAD_SWITCHING_OFF: case PAYLOAD_SWITCHING_OFF:
setDC_DC_ConvertersON(false); setDC_DC_ConvertersON(false);
sensor_array[HOT_SWAP_SENSOR].data->comparator_status |= HOT_SWAP_STATE_QUIESCED; /*
pmsg.dest_LUN = 0; hotswap_set_mask_bit( HOTSWAP_BACKEND_PWR_SHUTDOWN_MASK );
pmsg.netfn = NETFN_SE; hotswap_send_event( HOTSWAP_BACKEND_PWR_SHUTDOWN_MASK );
pmsg.cmd = IPMI_PLATFORM_EVENT_CMD; */
data_len = 0; hotswap_set_mask_bit( HOTSWAP_QUIESCED_MASK );
pmsg.data[data_len++] = 0x04; if ( hotswap_send_event( HOTSWAP_QUIESCED_MASK ) == ipmb_error_success ) {
pmsg.data[data_len++] = 0xf2; QUIESCED_req = 0;
pmsg.data[data_len++] = HOT_SWAP_SENSOR; /* Reset the power good flags to avoid the state machine to start over without a new read from the sensors */
pmsg.data[data_len++] = 0x6f; P12V_good = 0;
pmsg.data[data_len++] = HOT_SWAP_QUIESCED; // hot swap state P1V0_good = 0;
pmsg.data_len = data_len; new_state = PAYLOAD_NO_POWER;
if ( ipmb_send_request( &pmsg ) == ipmb_error_success ) { hotswap_clear_mask_bit( HOTSWAP_QUIESCED_MASK );
QUIESCED_req = 0; }
new_state = PAYLOAD_NO_POWER;
}
break; break;
default: default:
...@@ -282,4 +300,165 @@ void vTaskPayload(void *pvParmeters) ...@@ -282,4 +300,165 @@ void vTaskPayload(void *pvParmeters)
} }
} }
IPMI_HANDLER(ipmi_picmg_cmd_fru_control, NETFN_GRPEXT, IPMI_PICMG_CMD_FRU_CONTROL, ipmi_msg *req, ipmi_msg *rsp)
{
uint8_t len = rsp->data_len = 0;
uint8_t fru_ctl = req->data[2];
rsp->completion_code = IPMI_CC_OK;
switch (fru_ctl) {
case FRU_CTLCODE_COLD_RST:
payload_send_message(PAYLOAD_MESSAGE_COLD_RST);
break;
case FRU_CTLCODE_WARM_RST:
payload_send_message(PAYLOAD_MESSAGE_WARM_RST);
break;
case FRU_CTLCODE_REBOOT:
payload_send_message(PAYLOAD_MESSAGE_REBOOT);
break;
case FRU_CTLCODE_QUIESCE:
payload_send_message(PAYLOAD_MESSAGE_QUIESCED);
break;
default:
rsp->completion_code = IPMI_CC_INV_DATA_FIELD_IN_REQ;
break;
}
rsp->data[len++] = IPMI_PICMG_GRP_EXT;
rsp->data_len = len;
}
IPMI_HANDLER(ipmi_picmg_cmd_get_fru_control_capabilities, NETFN_GRPEXT, IPMI_PICMG_CMD_FRU_CONTROL_CAPABILITIES, ipmi_msg *req, ipmi_msg *rsp)
{
uint8_t len = rsp->data_len = 0;
rsp->data[len++] = IPMI_PICMG_GRP_EXT;
/* FRU Control Capabilities Mask:
* [7:4] Reserved
* [3] - Capable of issuing a diagnostic interrupt
* [2] - Capable of issuing a graceful reboot
* [1] - Capable of issuing a warm reset */
rsp->data[len++] = 0x06; /* Graceful reboot and Warm reset */
rsp->data_len = len;
rsp->completion_code = IPMI_CC_OK;
}
IPMI_HANDLER(ipmi_picmg_cmd_set_fru_activation_policy, NETFN_GRPEXT, IPMI_PICMG_CMD_SET_FRU_ACTIVATION_POLICY, ipmi_msg *req, ipmi_msg *rsp)
{
uint8_t len = rsp->data_len = 0;
/* FRU Activation Policy Mask */
uint8_t fru_actv_mask = req->data[2];
uint8_t fru_actv_bits = req->data[3];
/* TODO: Implement FRU activation policy */
rsp->data[len++] = IPMI_PICMG_GRP_EXT;
rsp->data_len = len;
rsp->completion_code = IPMI_CC_OK;
}
/* HPM Functions */
#ifdef MODULE_HPM
#include "flash_spi.h"
#include "string.h"
uint8_t hpm_page[256];
uint8_t hpm_pg_index;
uint32_t hpm_page_addr;
uint8_t payload_hpm_prepare_comp( void )
{
/* Initialize variables */
memset(hpm_page, 0xFF, sizeof(hpm_page));
hpm_pg_index = 0;
hpm_page_addr = 0;
/* Initialize flash */
ssp_init( FLASH_SPI, FLASH_SPI_BITRATE, FLASH_SPI_FRAME_SIZE, SSP_MASTER, SSP_INTERRUPT );
/* Prevent the FPGA from accessing the Flash to configure itself now */
gpio_set_pin_dir( GPIO_PROGRAM_B_PORT, GPIO_PROGRAM_B_PIN, OUTPUT);
gpio_set_pin_state( GPIO_PROGRAM_B_PORT, GPIO_PROGRAM_B_PIN, HIGH);
gpio_set_pin_state( GPIO_PROGRAM_B_PORT, GPIO_PROGRAM_B_PIN, LOW);
gpio_set_pin_state( GPIO_PROGRAM_B_PORT, GPIO_PROGRAM_B_PIN, HIGH);
gpio_set_pin_state( GPIO_PROGRAM_B_PORT, GPIO_PROGRAM_B_PIN, LOW);
/* Erase FLASH */
flash_bulk_erase();
return IPMI_CC_COMMAND_IN_PROGRESS;
}
uint8_t payload_hpm_upload_block( uint8_t * block, uint16_t size )
{
/* TODO: Check DONE pin before accessing the SPI bus, since the FPGA may be reading it in order to boot */
uint8_t remaining_bytes_start;
if ( sizeof(hpm_page) - hpm_pg_index > size) {
/* Our page is not full yet, just append the new data */
memcpy(&hpm_page[hpm_pg_index], block, size);
hpm_pg_index += size;
return IPMI_CC_OK;
} else {
/* Complete the remaining bytes on the buffer */
memcpy(&hpm_page[hpm_pg_index], block, (sizeof(hpm_page) - hpm_pg_index));
remaining_bytes_start = (sizeof(hpm_page) - hpm_pg_index);
/* Program the complete page in the Flash */
flash_program_page( hpm_page_addr, &hpm_page[0], sizeof(hpm_page));
hpm_page_addr += sizeof(hpm_page);
/* Empty our buffer and reset the index */
memset(hpm_page, 0xFF, sizeof(hpm_page));
hpm_pg_index = 0;
/* Save the trailing bytes */
memcpy(&hpm_page[hpm_pg_index], block+remaining_bytes_start, size-remaining_bytes_start);
hpm_pg_index = size-remaining_bytes_start;
return IPMI_CC_COMMAND_IN_PROGRESS;
}
}
uint8_t payload_hpm_finish_upload( uint32_t image_size )
{
/* Check if the last page was already programmed */
if (!hpm_pg_index) {
/* Program the complete page in the Flash */
flash_program_page( hpm_page_addr, &hpm_page[0], (sizeof(hpm_page)-hpm_pg_index));
hpm_pg_index = 0;
hpm_page_addr = 0;
return IPMI_CC_COMMAND_IN_PROGRESS;
}
return IPMI_CC_OK;
}
uint8_t payload_hpm_get_upgrade_status( void )
{
if (is_flash_busy()) {
return IPMI_CC_COMMAND_IN_PROGRESS;
} else {
return IPMI_CC_OK;
}
}
uint8_t payload_hpm_activate_firmware( void )
{
/* Reset FPGA - Pulse PROGRAM_B pin */
gpio_set_pin_state( GPIO_PROGRAM_B_PORT, GPIO_PROGRAM_B_PIN, LOW);
gpio_set_pin_state( GPIO_PROGRAM_B_PORT, GPIO_PROGRAM_B_PIN, HIGH);
return IPMI_CC_OK;
}
#endif
/* /*
* payload.h * openMMC -- Open Source modular IPM Controller firmware
* *
* AFCIPMI -- * Copyright (C) 2015 Piotr Miedzik <P.Miedzik@gsi.de>
* * Copyright (C) 2015-2016 Henrique Silva <henrique.silva@lnls.br>
* Copyright (C) 2015 Piotr Miedzik <P.Miedzik@gsi.de>
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
...@@ -17,35 +16,37 @@ ...@@ -17,35 +16,37 @@
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* @license GPL-3.0+ <http://spdx.org/licenses/GPL-3.0+>
*/ */
#ifndef IPMI_PAYLOAD_H_ #ifndef IPMI_PAYLOAD_H_
#define IPMI_PAYLOAD_H_ #define IPMI_PAYLOAD_H_
typedef enum { typedef enum {
PAYLOAD_NO_POWER = 0, PAYLOAD_NO_POWER = 0,
PAYLOAD_SWITCHING_ON = 1, PAYLOAD_SWITCHING_ON,
PAYLOAD_POWER_GOOD_WAIT = 3, PAYLOAD_POWER_GOOD_WAIT,
PAYLOAD_STATE_FPGA_SETUP = 4, PAYLOAD_STATE_FPGA_SETUP,
PAYLOAD_FPGA_BOOTING = 5, PAYLOAD_FPGA_BOOTING,
PAYLOAD_FPGA_WORKING = 6, PAYLOAD_FPGA_WORKING,
PAYLOAD_SWITCHING_OFF = 7, PAYLOAD_SWITCHING_OFF,
PAYLOAD_QUIESCED = 8, PAYLOAD_QUIESCED,
PAYLOAD_OFF = 9, PAYLOAD_OFF,
PAYLOAD_STATE_NO_CHANGE = 253, PAYLOAD_STATE_NO_CHANGE = 253,
PAYLOAD_STATE_UNKNOWN = 254, PAYLOAD_STATE_UNKNOWN = 254,
PAYLOAD_POWER_FAIL = 255 PAYLOAD_POWER_FAIL = 255
} payload_state; } payload_state;
typedef enum { typedef enum {
PAYLOAD_MESSAGE_P12GOOD, PAYLOAD_MESSAGE_P12GOOD,
PAYLOAD_MESSAGE_P12GOODn, PAYLOAD_MESSAGE_P12GOODn,
PAYLOAD_MESSAGE_PGOOD, PAYLOAD_MESSAGE_PGOOD,
PAYLOAD_MESSAGE_PGOODn, PAYLOAD_MESSAGE_PGOODn,
PAYLOAD_MESSAGE_COLD_RST, PAYLOAD_MESSAGE_COLD_RST,
PAYLOAD_MESSAGE_WARM_RST, PAYLOAD_MESSAGE_WARM_RST,
PAYLOAD_MESSAGE_REBOOT, PAYLOAD_MESSAGE_REBOOT,
PAYLOAD_MESSAGE_QUIESCED PAYLOAD_MESSAGE_QUIESCED
} payload_message; } payload_message;
#define FRU_CTLCODE_COLD_RST (0) // FRU Control command cold reset code #define FRU_CTLCODE_COLD_RST (0) // FRU Control command cold reset code
...@@ -53,10 +54,18 @@ typedef enum { ...@@ -53,10 +54,18 @@ typedef enum {
#define FRU_CTLCODE_REBOOT (2) // FRU Control command reboot code #define FRU_CTLCODE_REBOOT (2) // FRU Control command reboot code
#define FRU_CTLCODE_QUIESCE (4) // FRU Control command quiesce code #define FRU_CTLCODE_QUIESCE (4) // FRU Control command quiesce code
#define PAYLOAD_BASE_DELAY 200 #define PAYLOAD_BASE_DELAY 100
void payload_send_message(uint8_t msg); void payload_send_message(uint8_t msg);
void vTaskPayload(void *pvParmeters); void vTaskPayload(void *pvParameters);
void payload_init(void); void payload_init(void);
#ifdef MODULE_HPM
uint8_t payload_hpm_prepare_comp( void );
uint8_t payload_hpm_upload_block( uint8_t * block, uint16_t size );
uint8_t payload_hpm_finish_upload( uint32_t image_size );
uint8_t payload_hpm_get_upgrade_status( void );
uint8_t payload_hpm_activate_firmware( void );
#endif
#endif /* IPMI_PAYLOAD_H_ */ #endif /* IPMI_PAYLOAD_H_ */
/* /*
* sdr.c * openMMC -- Open Source modular IPM Controller firmware
*
* AFCIPMI --
* *
* Copyright (C) 2015 Piotr Miedzik <P.Miedzik@gsi.de> * Copyright (C) 2015 Piotr Miedzik <P.Miedzik@gsi.de>
* Copyright (C) 2015-2016 Henrique Silva <henrique.silva@lnls.br>
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
...@@ -17,567 +16,25 @@ ...@@ -17,567 +16,25 @@
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* @license GPL-3.0+ <http://spdx.org/licenses/GPL-3.0+>
*/ */
/* FreeRTOS Includes */
#include "FreeRTOS.h" #include "FreeRTOS.h"
#include "task.h" #include "task.h"
#include "semphr.h" #include "semphr.h"
/* Project Includes */
#include "sdr.h" #include "sdr.h"
#include "sensors.h" #include "sensors.h"
#include "pin_mapping.h"
#include "i2c.h"
#include "port.h"
#include "ipmi.h" #include "ipmi.h"
#include "ipmb.h"
#include "payload.h"
#include "board_version.h"
#include "led.h"
#include "task_priorities.h"
#include "fpga_spi.h" #include "fpga_spi.h"
/* Management Controller Device Locator Record 37.9 SDR Type 12h */ sensor_t *sensor_array = NULL;
static const SDR_type_12h_t SDR0 = { uint8_t sdr_count = 0;
.hdr.recID_LSB = 0x00, /* record number, LSB - filled by sdr_init() */
.hdr.recID_MSB = 0x00, /* record number, MSB - filled by sdr_init() */
.hdr.SDRversion = 0x51, /* IPMI protocol version */
.hdr.rectype = TYPE_12, /* record type: device locator record */
.hdr.reclength = sizeof(SDR_type_12h_t) - sizeof(SDR_entry_hdr_t), /* record length - filled by sdr_init() */
/* record key bytes */
.slaveaddr = 0x00, // owner ID??
.chnum = 0x00,
.power_notification_global_init = 0x04,
.device_cap = 0x3b,
.reserved[0] = 0x00,
.reserved[1] = 0x00,
.reserved[2] = 0x00,
.entityID = 0xC1,
.entityinstance = 0x00,
.OEM = 0x00,
.IDtypelen = 0xc7, /* 8 bit ASCII, number of bytes */
.IDstring = {'A', 'F', 'C', ' ', 'I', 'P', 'M' }
};
/* Hot-Swap sensor */
static const SDR_type_02h_t SDR_HOT_SWAP = {
.hdr.recID_LSB = HOT_SWAP_SENSOR,
.hdr.recID_MSB = 0x00,
.hdr.SDRversion = 0x51,
.hdr.rectype = TYPE_02,
.hdr.reclength = sizeof(SDR_type_02h_t) - sizeof(SDR_entry_hdr_t),
.ownerID = 0x00, /* i2c address, -> SDR_Init */
.ownerLUN = 0x00, /* sensor owner LUN */
.sensornum = HOT_SWAP_SENSOR, /* sensor number */
/* record body bytes */
.entityID = 0xC1, /* entity id: AMC Module */
.entityinstance = 0x00, /* entity instance -> SDR_Init */
.sensorinit = 0x03, /* init: event generation + scanning enabled */
.sensorcap = 0xc1, /* capabilities: auto re-arm,*/
.sensortype = SENSOR_TYPE_HOT_SWAP, /* sensor type: HOT SWAP*/
.event_reading_type = 0x6f, /* sensor reading*/
.assertion_event_mask = { 0x00, /* LSB assert event mask: 3 bit value */
0x00 }, /* MSB assert event mask */
.deassertion_event_mask = { 0x00, /* LSB deassert event mask: 3 bit value */
0x00 }, /* MSB deassert event mask */
.readable_threshold_mask = 0x00, /* LSB: readable Threshold mask: no thresholds are readable: */
.settable_threshold_mask = 0x00, /* MSB: setable Threshold mask: no thresholds are setable: */
.sensor_units_1 = 0xc0, /* sensor units 1 : Does not return analog reading*/
.sensor_units_2 = 0x00, /* sensor units 2 :*/
.sensor_units_3 = 0x00, /* sensor units 3 :*/
.record_sharing[0] = 0x00,
.record_sharing[1] = 0x00,
.pos_thr_hysteresis = 0x00, /* positive going Threshold hysteresis value */
.neg_thr_hysteresis = 0x00, /* negative going Threshold hysteresis value */
.reserved1 = 0x00, /* reserved */
.reserved2 = 0x00, /* reserved */
.reserved3 = 0x00, /* reserved */
.OEM = 0x00, /* OEM reserved */
.IDtypelen = 0xcF, /* 8 bit ASCII, number of bytes */
.IDstring = { 'M', 'O', 'D', 'U', 'L', 'E', ' ', 'H', 'O', 'T', '_', 'S', 'W', 'A', 'P' } /* sensor string */
};
/* 12V sensor */
static const SDR_type_01h_t SDR_FMC1_12V = {
.hdr.recID_LSB = NUM_SDR_FMC1_12V,
.hdr.recID_MSB = 0x00,
.hdr.SDRversion = 0x51,
.hdr.rectype = TYPE_01,
.hdr.reclength = sizeof(SDR_type_01h_t) - sizeof(SDR_entry_hdr_t),
.ownerID = 0x00, /* i2c address, -> SDR_Init */
.ownerLUN = 0x00, /* sensor owner LUN */
.sensornum = NUM_SDR_FMC1_12V, /* sensor number */
/* record body bytes */
.entityID = 0xC1, /* entity id: AMC Module */
.entityinstance = 0x00, /* entity instance -> SDR_Init */
.sensorinit = 0x7f, /* init: event generation + scanning enabled */
.sensorcap = 0x58, /* capabilities: auto re-arm,*/
.sensortype = SENSOR_TYPE_VOLTAGE, /* sensor type: Voltage*/
.event_reading_type = 0x01, /* sensor reading*/
.assertion_event_mask = { 0xFF, /* LSB assert event mask: 3 bit value */
0x0F }, /* MSB assert event mask */
.deassertion_event_mask = { 0xFF, /* LSB deassert event mask: 3 bit value */
0x0F }, /* MSB deassert event mask */
.readable_threshold_mask = 0x3F, /* LSB: readabled Threshold mask: all thresholds are readabled: */
.settable_threshold_mask = 0x3F, /* MSB: setabled Threshold mask: all thresholds are setabled: */
.sensor_units_1 = 0x00, /* sensor units 1 :*/
.sensor_units_2 = 0x04, /* sensor units 2 :*/
.sensor_units_3 = 0x00, /* sensor units 3 :*/
.linearization = 0x00, /* Linearization */
.M = 1, /* M */
.M_tol = 0x00, /* M - Tolerance */
.B = 0x00, /* B */
.B_accuracy = 0x00, /* B - Accuracy */
.acc_exp_sensor_dir = 0x02, /* Sensor direction */
.Rexp_Bexp = 0xF0, /* R-Exp = -3 , B-Exp = 0 */
.analog_flags = 0x03, /* Analogue characteristics flags */
.nominal_reading = 195, /* Nominal reading = 12.285V */
.normal_max = 255, /* Normal maximum */
.normal_min = 0x00, /* Normal minimum */
.sensor_max_reading = 255, /* Sensor Maximum reading */
.sensor_min_reading = 0x00, /* Sensor Minimum reading */
.upper_nonrecover_thr = 250, /* Upper non-recoverable Threshold */
.upper_critical_thr = 236, /* Upper critical Threshold */
.upper_noncritical_thr = 225, /* Upper non critical Threshold */
.lower_nonrecover_thr = 193, /* Lower non-recoverable Threshold */
.lower_critical_thr = 174, /* Lower critical Threshold */
.lower_noncritical_thr = 178, /* Lower non-critical Threshold */
.pos_thr_hysteresis = 2, /* positive going Threshold hysteresis value */
.neg_thr_hysteresis = 2, /* negative going Threshold hysteresis value */
.reserved1 = 0x00, /* reserved */
.reserved2 = 0x00, /* reserved */
.OEM = 0x00, /* OEM reserved */
.IDtypelen = 0xc0 | 9 , /* 8 bit ASCII, number of bytes */
.IDstring = { 'F','M','C','1',' ','+', '1', '2', 'V' } /* sensor string */
};
/* FMC2 PVADJ sensor */
static const SDR_type_01h_t SDR_FMC1_VADJ = {
.hdr.recID_LSB = NUM_SDR_FMC1_VADJ,
.hdr.recID_MSB = 0x00,
.hdr.SDRversion = 0x51,
.hdr.rectype = TYPE_01,
.hdr.reclength = sizeof(SDR_type_01h_t) - sizeof(SDR_entry_hdr_t),
.ownerID = 0x00, /* i2c address, -> SDR_Init */
.ownerLUN = 0x00, /* sensor owner LUN */
.sensornum = NUM_SDR_FMC1_VADJ, /* sensor number */
/* record body bytes */
.entityID = 0xC1, /* entity id: AMC Module */
.entityinstance = 0x00, /* entity instance -> SDR_Init */
.sensorinit = 0x7f, /* init: event generation + scanning enabled */
.sensorcap = 0x58, /* capabilities: auto re-arm,*/
.sensortype = SENSOR_TYPE_VOLTAGE, /* sensor type: voltage*/
.event_reading_type = 0x01, /* sensor reading*/
.assertion_event_mask = { 0x07, /* LSB assert event mask: 3 bit value */
0x00 }, /* MSB assert event mask */
.deassertion_event_mask = { 0x07, /* LSB deassert event mask: 3 bit value */
0x00 }, /* MSB deassert event mask */
.readable_threshold_mask = 0x00, /* LSB: readabled Threshold mask: all thresholds are readabled: */
.settable_threshold_mask = 0x00, /* MSB: setabled Threshold mask: all thresholds are setabled: */
.sensor_units_1 = 0xc0, /* sensor units 1 :*/
.sensor_units_2 = 0x4, /* sensor units 2 :*/
.sensor_units_3 = 0x00, /* sensor units 3 :*/
.linearization = 0x00, /* Linearization */
.M = 1, /* M */
.M_tol = 0x00, /* M - Tolerance */
.B = 0x00, /* B */
.B_accuracy = 0x00, /* B - Accuracy */
.acc_exp_sensor_dir = 0x00, /* Sensor direction */
.Rexp_Bexp = 0xF0, /* R-Exp , B-Exp */
.analog_flags = 0x00, /* Analogue characteristics flags */
.nominal_reading = 195, /* Nominal reading */
.normal_max = 255, /* Normal maximum */
.normal_min = 0x00, /* Normal minimum */
.sensor_max_reading = 255, /* Sensor Maximum reading */
.sensor_min_reading = 0x00, /* Sensor Minimum reading */
.upper_nonrecover_thr = 250, /* Upper non-recoverable Threshold */
.upper_critical_thr = 236, /* Upper critical Threshold */
.upper_noncritical_thr = 225, /* Upper non critical Threshold */
.lower_nonrecover_thr = 193, /* Lower non-recoverable Threshold */
.lower_critical_thr = 174, /* Lower critical Threshold */
.lower_noncritical_thr = 178, /* Lower non-critical Threshold */
.pos_thr_hysteresis = 2, /* positive going Threshold hysteresis value */
.neg_thr_hysteresis = 2, /* negative going Threshold hysteresis value */
.reserved1 = 0x00, /* reserved */
.reserved2 = 0x00, /* reserved */
.OEM = 0x00, /* OEM reserved */
.IDtypelen = 0xc0 | 9, /* 8 bit ASCII, number of bytes */
.IDstring = { 'F','M','C','1',' ', 'V', 'A', 'D', 'J' } /* sensor string */
};
/* FMC2 PVADJ sensor */
static const SDR_type_01h_t SDR_FMC1_P3V3 = {
.hdr.recID_LSB = NUM_SDR_FMC1_3V3,
.hdr.recID_MSB = 0x00,
.hdr.SDRversion = 0x51,
.hdr.rectype = TYPE_01,
.hdr.reclength = sizeof(SDR_type_01h_t) - sizeof(SDR_entry_hdr_t),
.ownerID = 0x00, /* i2c address, -> SDR_Init */
.ownerLUN = 0x00, /* sensor owner LUN */
.sensornum = NUM_SDR_FMC1_3V3, /* sensor number */
/* record body bytes */
.entityID = 0xC1, /* entity id: AMC Module */
.entityinstance = 0x00, /* entity instance -> SDR_Init */
.sensorinit = 0x7f, /* init: event generation + scanning enabled */
.sensorcap = 0x58, /* capabilities: auto re-arm,*/
.sensortype = SENSOR_TYPE_VOLTAGE, /* sensor type: VOLTAGE*/
.event_reading_type = 0x01, /* sensor reading*/
.assertion_event_mask = { 0x07, /* LSB assert event mask: 3 bit value */
0x00 }, /* MSB assert event mask */
.deassertion_event_mask = { 0x07, /* LSB deassert event mask: 3 bit value */
0x00 }, /* MSB deassert event mask */
.readable_threshold_mask = 0x00, /* LSB: readabled Threshold mask: all thresholds are readabled: */
.settable_threshold_mask = 0x00, /* MSB: setabled Threshold mask: all thresholds are setabled: */
.sensor_units_1 = 0xc0, /* sensor units 1 :*/
.sensor_units_2 = 0x4, /* sensor units 2 :*/
.sensor_units_3 = 0x00, /* sensor units 3 :*/
.linearization = 0x00, /* Linearization */
.M = 1, /* M */
.M_tol = 0x00, /* M - Tolerance */
.B = 0x00, /* B */
.B_accuracy = 0x00, /* B - Accuracy */
.acc_exp_sensor_dir = 0x00, /* Sensor direction */
.Rexp_Bexp = 0xF0, /* R-Exp , B-Exp */
.analog_flags = 0x00, /* Analogue characteristics flags */
.nominal_reading = 33, /* Nominal reading */
.normal_max = 255, /* Normal maximum */
.normal_min = 0x00, /* Normal minimum */
.sensor_max_reading = 255, /* Sensor Maximum reading */
.sensor_min_reading = 0x00, /* Sensor Minimum reading */
.upper_nonrecover_thr = 40, /* Upper non-recoverable Threshold */
.upper_critical_thr = 38, /* Upper critical Threshold */
.upper_noncritical_thr = 36, /* Upper non critical Threshold */
.lower_nonrecover_thr = 26, /* Lower non-recoverable Threshold */
.lower_critical_thr = 28, /* Lower critical Threshold */
.lower_noncritical_thr = 30, /* Lower non-critical Threshold */
.pos_thr_hysteresis = 2, /* positive going Threshold hysteresis value */
.neg_thr_hysteresis = 2, /* negative going Threshold hysteresis value */
.reserved1 = 0x00, /* reserved */
.reserved2 = 0x00, /* reserved */
.OEM = 0x00, /* OEM reserved */
.IDtypelen = 0xc0 | 9, /* 8 bit ASCII, number of bytes */
.IDstring = { 'F','M','C','1',' ', '+', '3', 'V', '3' } /* sensor string */
};
/* 12V sensor */
static const SDR_type_01h_t SDR_FMC2_12V = {
.hdr.recID_LSB = NUM_SDR_FMC2_12V, static uint16_t reservationID;
.hdr.recID_MSB = 0x00,
.hdr.SDRversion = 0x51,
.hdr.rectype = TYPE_01,
.hdr.reclength = sizeof(SDR_type_01h_t) - sizeof(SDR_entry_hdr_t),
.ownerID = 0x00, /* i2c address, -> SDR_Init */
.ownerLUN = 0x00, /* sensor owner LUN */
.sensornum = NUM_SDR_FMC2_12V, /* sensor number */
/* record body bytes */
.entityID = 0xC1, /* entity id: AMC Module */
.entityinstance = 0x00, /* entity instance -> SDR_Init */
.sensorinit = 0x7f, /* init: event generation + scanning enabled */
.sensorcap = 0x58, /* capabilities: auto re-arm,*/
.sensortype = SENSOR_TYPE_VOLTAGE, /* sensor type: Voltage*/
.event_reading_type = 0x01, /* sensor reading*/
.assertion_event_mask = { 0xFF, /* LSB assert event mask: 3 bit value */
0x0F }, /* MSB assert event mask */
.deassertion_event_mask = { 0xFF, /* LSB deassert event mask: 3 bit value */
0x0F }, /* MSB deassert event mask */
.readable_threshold_mask = 0x3F, /* LSB: readabled Threshold mask: all thresholds are readabled: */
.settable_threshold_mask = 0x3F, /* MSB: setabled Threshold mask: all thresholds are setabled: */
.sensor_units_1 = 0x00, /* sensor units 1 :*/
.sensor_units_2 = 0x04, /* sensor units 2 :*/
.sensor_units_3 = 0x00, /* sensor units 3 :*/
.linearization = 0x00, /* Linearization */
.M = 1, /* M */
.M_tol = 0x00, /* M - Tolerance */
.B = 0x00, /* B */
.B_accuracy = 0x00, /* B - Accuracy */
.acc_exp_sensor_dir = 0x02, /* Sensor direction */
.Rexp_Bexp = 0xF0, /* R-Exp = -3 , B-Exp = 0 */
.analog_flags = 0x03, /* Analogue characteristics flags */
.nominal_reading = 125, /* Nominal reading = 12.285V */
.normal_max = 255, /* Normal maximum */
.normal_min = 0x00, /* Normal minimum */
.sensor_max_reading = 255, /* Sensor Maximum reading */
.sensor_min_reading = 0x00, /* Sensor Minimum reading */
.upper_nonrecover_thr = 250, /* Upper non-recoverable Threshold */
.upper_critical_thr = 130, /* Upper critical Threshold */
.upper_noncritical_thr = 128, /* Upper non critical Threshold */
.lower_nonrecover_thr = 100, /* Lower non-recoverable Threshold */
.lower_critical_thr = 110, /* Lower critical Threshold */
.lower_noncritical_thr = 115, /* Lower non-critical Threshold */
.pos_thr_hysteresis = 2, /* positive going Threshold hysteresis value */
.neg_thr_hysteresis = 2, /* negative going Threshold hysteresis value */
.reserved1 = 0x00, /* reserved */
.reserved2 = 0x00, /* reserved */
.OEM = 0x00, /* OEM reserved */
.IDtypelen = 0xc0 | 9 , /* 8 bit ASCII, number of bytes */
.IDstring = { 'F','M','C','2',' ','+', '1', '2', 'V' } /* sensor string */
};
/* FMC2 PVADJ sensor */
static const SDR_type_01h_t SDR_FMC2_VADJ = {
.hdr.recID_LSB = NUM_SDR_FMC2_VADJ,
.hdr.recID_MSB = 0x00,
.hdr.SDRversion = 0x51,
.hdr.rectype = TYPE_01,
.hdr.reclength = sizeof(SDR_type_01h_t) - sizeof(SDR_entry_hdr_t),
.ownerID = 0x00, /* i2c address, -> SDR_Init */
.ownerLUN = 0x00, /* sensor owner LUN */
.sensornum = NUM_SDR_FMC2_VADJ, /* sensor number */
/* record body bytes */
.entityID = 0xC1, /* entity id: AMC Module */
.entityinstance = 0x00, /* entity instance -> SDR_Init */
.sensorinit = 0x7f, /* init: event generation + scanning enabled */
.sensorcap = 0x58, /* capabilities: auto re-arm,*/
.sensortype = SENSOR_TYPE_VOLTAGE, /* sensor type: voltage*/
.event_reading_type = 0x01, /* sensor reading*/
.assertion_event_mask = { 0x07, /* LSB assert event mask: 3 bit value */
0x00 }, /* MSB assert event mask */
.deassertion_event_mask = { 0x07, /* LSB deassert event mask: 3 bit value */
0x00 }, /* MSB deassert event mask */
.readable_threshold_mask = 0x00, /* LSB: readabled Threshold mask: all thresholds are readabled: */
.settable_threshold_mask = 0x00, /* MSB: setabled Threshold mask: all thresholds are setabled: */
.sensor_units_1 = 0xc0, /* sensor units 1 :*/
.sensor_units_2 = 0x4, /* sensor units 2 :*/
.sensor_units_3 = 0x00, /* sensor units 3 :*/
.linearization = 0x00, /* Linearization */
.M = 1, /* M */
.M_tol = 0x00, /* M - Tolerance */
.B = 0x00, /* B */
.B_accuracy = 0x00, /* B - Accuracy */
.acc_exp_sensor_dir = 0x00, /* Sensor direction */
.Rexp_Bexp = 0xF0, /* R-Exp , B-Exp */
.analog_flags = 0x00, /* Analogue characteristics flags */
.nominal_reading = 195, /* Nominal reading */
.normal_max = 255, /* Normal maximum */
.normal_min = 0x00, /* Normal minimum */
.sensor_max_reading = 255, /* Sensor Maximum reading */
.sensor_min_reading = 0x00, /* Sensor Minimum reading */
.upper_nonrecover_thr = 250, /* Upper non-recoverable Threshold */
.upper_critical_thr = 236, /* Upper critical Threshold */
.upper_noncritical_thr = 225, /* Upper non critical Threshold */
.lower_nonrecover_thr = 193, /* Lower non-recoverable Threshold */
.lower_critical_thr = 174, /* Lower critical Threshold */
.lower_noncritical_thr = 178, /* Lower non-critical Threshold */
.pos_thr_hysteresis = 2, /* positive going Threshold hysteresis value */
.neg_thr_hysteresis = 2, /* negative going Threshold hysteresis value */
.reserved1 = 0x00, /* reserved */
.reserved2 = 0x00, /* reserved */
.OEM = 0x00, /* OEM reserved */
.IDtypelen = 0xc0 | 9, /* 8 bit ASCII, number of bytes */
.IDstring = { 'F','M','C','2',' ', 'V', 'A', 'D', 'J' } /* sensor string */
};
/* FMC2 PVADJ sensor */
static const SDR_type_01h_t SDR_FMC2_P3V3 = {
.hdr.recID_LSB = NUM_SDR_FMC2_3V3,
.hdr.recID_MSB = 0x00,
.hdr.SDRversion = 0x51,
.hdr.rectype = TYPE_01,
.hdr.reclength = sizeof(SDR_type_01h_t) - sizeof(SDR_entry_hdr_t),
.ownerID = 0x00, /* i2c address, -> SDR_Init */
.ownerLUN = 0x00, /* sensor owner LUN */
.sensornum = NUM_SDR_FMC2_3V3, /* sensor number */
/* record body bytes */
.entityID = 0xC1, /* entity id: AMC Module */
.entityinstance = 0x00, /* entity instance -> SDR_Init */
.sensorinit = 0x7f, /* init: event generation + scanning enabled */
.sensorcap = 0x58, /* capabilities: auto re-arm,*/
.sensortype = SENSOR_TYPE_VOLTAGE, /* sensor type: VOLTAGE*/
.event_reading_type = 0x01, /* sensor reading*/
.assertion_event_mask = { 0x07, /* LSB assert event mask: 3 bit value */
0x00 }, /* MSB assert event mask */
.deassertion_event_mask = { 0x07, /* LSB deassert event mask: 3 bit value */
0x00 }, /* MSB deassert event mask */
.readable_threshold_mask = 0x00, /* LSB: readabled Threshold mask: all thresholds are readabled: */
.settable_threshold_mask = 0x00, /* MSB: setabled Threshold mask: all thresholds are setabled: */
.sensor_units_1 = 0xc0, /* sensor units 1 :*/
.sensor_units_2 = 0x4, /* sensor units 2 :*/
.sensor_units_3 = 0x00, /* sensor units 3 :*/
.linearization = 0x00, /* Linearization */
.M = 1, /* M */
.M_tol = 0x00, /* M - Tolerance */
.B = 0x00, /* B */
.B_accuracy = 0x00, /* B - Accuracy */
.acc_exp_sensor_dir = 0x00, /* Sensor direction */
.Rexp_Bexp = 0xF0, /* R-Exp , B-Exp */
.analog_flags = 0x00, /* Analogue characteristics flags */
.nominal_reading = 33, /* Nominal reading */
.normal_max = 255, /* Normal maximum */
.normal_min = 0x00, /* Normal minimum */
.sensor_max_reading = 255, /* Sensor Maximum reading */
.sensor_min_reading = 0x00, /* Sensor Minimum reading */
.upper_nonrecover_thr = 40, /* Upper non-recoverable Threshold */
.upper_critical_thr = 38, /* Upper critical Threshold */
.upper_noncritical_thr = 36, /* Upper non critical Threshold */
.lower_nonrecover_thr = 26, /* Lower non-recoverable Threshold */
.lower_critical_thr = 28, /* Lower critical Threshold */
.lower_noncritical_thr = 30, /* Lower non-critical Threshold */
.pos_thr_hysteresis = 2, /* positive going Threshold hysteresis value */
.neg_thr_hysteresis = 2, /* negative going Threshold hysteresis value */
.reserved1 = 0x00, /* reserved */
.reserved2 = 0x00, /* reserved */
.OEM = 0x00, /* OEM reserved */
.IDtypelen = 0xc0 | 9, /* 8 bit ASCII, number of bytes */
.IDstring = { 'F','M','C','2',' ', '+', '3', 'V', '3' } /* sensor string */
};
static const SDR_type_01h_t SDR_LM75_1 = {
.hdr.recID_LSB = NUM_SDR_LM75_1,
.hdr.recID_MSB = 0x00,
.hdr.SDRversion = 0x51,
.hdr.rectype = TYPE_01,
.hdr.reclength = sizeof(SDR_type_01h_t) - sizeof(SDR_entry_hdr_t),
.ownerID = 0x00, /* i2c address, -> SDR_Init */
.ownerLUN = 0x00, /* sensor owner LUN */
.sensornum = NUM_SDR_LM75_1, /* sensor number */
/* record body bytes */
.entityID = 0xC1, /* entity id: AMC Module */
.entityinstance = 0x00, /* entity instance -> SDR_Init */
.sensorinit = 0x7f, /* init: event generation + scanning enabled */
.sensorcap = 0x68, /* capabilities: auto re-arm,*/
.sensortype = SENSOR_TYPE_TEMPERATURE, /* sensor type */
.event_reading_type = 0x01, /* sensor reading*/
.assertion_event_mask = { 0xFF, /* LSB assert event mask: 3 bit value */
0x0F }, /* MSB assert event mask */
.deassertion_event_mask = { 0xFF, /* LSB deassert event mask: 3 bit value */
0x0F }, /* MSB deassert event mask */
.readable_threshold_mask = 0x3F, /* LSB: readabled Threshold mask: all thresholds are readabled: */
.settable_threshold_mask = 0x3F, /* MSB: setabled Threshold mask: all thresholds are setabled: */
.sensor_units_1 = 0x00, /* sensor units 1 :*/
.sensor_units_2 = 0x01, /* sensor units 2 :*/
.sensor_units_3 = 0x00, /* sensor units 3 :*/
.linearization = 0x00, /* Linearization */
.M = 1, /* M */
.M_tol = 0x00, /* M - Tolerance */
.B = 0x00, /* B */
.B_accuracy = 0x00, /* B - Accuracy */
.acc_exp_sensor_dir = 0x00, /* Sensor direction */
.Rexp_Bexp = 0xF0, /* R-Exp , B-Exp */
.analog_flags = 0x03, /* Analogue characteristics flags */
.nominal_reading = 30, /* Nominal reading */
.normal_max = 50, /* Normal maximum */
.normal_min = 20, /* Normal minimum */
.sensor_max_reading = 127, /* Sensor Maximum reading */
.sensor_min_reading = 0, /* Sensor Minimum reading */
.upper_nonrecover_thr = 75, /* Upper non-recoverable Threshold */
.upper_critical_thr = 65, /* Upper critical Threshold */
.upper_noncritical_thr = 60, /* Upper non critical Threshold */
.lower_nonrecover_thr = 5, /* Lower non-recoverable Threshold */
.lower_critical_thr = 10, /* Lower critical Threshold */
.lower_noncritical_thr = 15, /* Lower non-critical Threshold */
.pos_thr_hysteresis = 2, /* positive going Threshold hysteresis value */
.neg_thr_hysteresis = 2, /* negative going Threshold hysteresis value */
.reserved1 = 0x00, /* reserved */
.reserved2 = 0x00, /* reserved */
.OEM = 0x00, /* OEM reserved */
.IDtypelen = 0xc0 | 6, /* 8 bit ASCII, number of bytes */
.IDstring = { 'T','E','M','P',' ', '1' } /* sensor string */
};
static const SDR_type_01h_t SDR_LM75_2 = {
.hdr.recID_LSB = NUM_SDR_LM75_2,
.hdr.recID_MSB = 0x00,
.hdr.SDRversion = 0x51,
.hdr.rectype = TYPE_01,
.hdr.reclength = sizeof(SDR_type_01h_t) - sizeof(SDR_entry_hdr_t),
.ownerID = 0x00, /* i2c address, -> SDR_Init */
.ownerLUN = 0x00, /* sensor owner LUN */
.sensornum = NUM_SDR_LM75_2, /* sensor number */
/* record body bytes */
.entityID = 0xC1, /* entity id: AMC Module */
.entityinstance = 0x00, /* entity instance -> SDR_Init */
.sensorinit = 0x7f, /* init: event generation + scanning enabled */
.sensorcap = 0x68, /* capabilities: auto re-arm,*/
.sensortype = SENSOR_TYPE_TEMPERATURE, /* sensor type */
.event_reading_type = 0x01, /* sensor reading*/
.assertion_event_mask = { 0xFF, /* LSB assert event mask: 3 bit value */
0x0F }, /* MSB assert event mask */
.deassertion_event_mask = { 0xFF, /* LSB deassert event mask: 3 bit value */
0x0F }, /* MSB deassert event mask */
.readable_threshold_mask = 0x3F, /* LSB: readabled Threshold mask: all thresholds are readabled: */
.settable_threshold_mask = 0x3F, /* MSB: setabled Threshold mask: all thresholds are setabled: */
.sensor_units_1 = 0x00, /* sensor units 1 :*/
.sensor_units_2 = 0x01, /* sensor units 2 :*/
.sensor_units_3 = 0x00, /* sensor units 3 :*/
.linearization = 0x00, /* Linearization */
.M = 1, /* M */
.M_tol = 0x00, /* M - Tolerance */
.B = 0x00, /* B */
.B_accuracy = 0x00, /* B - Accuracy */
.acc_exp_sensor_dir = 0x00, /* Sensor direction */
.Rexp_Bexp = 0xF0, /* R-Exp , B-Exp */
.analog_flags = 0x03, /* Analogue characteristics flags */
.nominal_reading = 30, /* Nominal reading */
.normal_max = 50, /* Normal maximum */
.normal_min = 20, /* Normal minimum */
.sensor_max_reading = 127, /* Sensor Maximum reading */
.sensor_min_reading = 0, /* Sensor Minimum reading */
.upper_nonrecover_thr = 75, /* Upper non-recoverable Threshold */
.upper_critical_thr = 65, /* Upper critical Threshold */
.upper_noncritical_thr = 60, /* Upper non critical Threshold */
.lower_nonrecover_thr = 5, /* Lower non-recoverable Threshold */
.lower_critical_thr = 10, /* Lower critical Threshold */
.lower_noncritical_thr = 15, /* Lower non-critical Threshold */
.pos_thr_hysteresis = 2, /* positive going Threshold hysteresis value */
.neg_thr_hysteresis = 2, /* negative going Threshold hysteresis value */
.reserved1 = 0x00, /* reserved */
.reserved2 = 0x00, /* reserved */
.OEM = 0x00, /* OEM reserved */
.IDtypelen = 0xc0 | 6, /* 8 bit ASCII, number of bytes */
.IDstring = { 'T','E','M','P',' ', '2' } /* sensor string */
};
TaskHandle_t vTaskHotSwap_Handle;
TaskHandle_t vTaskINA220_Handle;
sensor_data_entry_t sdrData[NUM_SDR];
const sensor_t const sensor_array[NUM_SDR];
const sensor_t const sensor_array[NUM_SDR] = {
/* Entry record */
{ TYPE_12, (void *) &SDR0, sizeof(SDR0), &sdrData[0], (TaskHandle_t *) NULL, 0 , NO_DIAG },
/* Hotswap Sensor */
{ TYPE_02, (void *) &SDR_HOT_SWAP, sizeof(SDR_HOT_SWAP), &sdrData[1], (TaskHandle_t *) &vTaskHotSwap_Handle, 0 , NO_DIAG },
/* FMC1 Current/Voltage/Power Sensors */
{ TYPE_01, (void *) &SDR_FMC1_12V, sizeof(SDR_FMC1_12V), &sdrData[2], (TaskHandle_t *) &vTaskINA220_Handle, 0x40, FMC1_12V_DEVID },
{ TYPE_01, (void *) &SDR_FMC1_VADJ, sizeof(SDR_FMC1_VADJ), &sdrData[3], (TaskHandle_t *) &vTaskINA220_Handle, 0x41, FMC1_VADJ_DEVID },
{ TYPE_01, (void *) &SDR_FMC1_P3V3, sizeof(SDR_FMC1_P3V3), &sdrData[4], (TaskHandle_t *) &vTaskINA220_Handle, 0x43, FMC1_P3V3_DEVID },
/* FMC2 Current/Voltage/Power Sensors */
{ TYPE_01, (void *) &SDR_FMC2_12V, sizeof(SDR_FMC2_12V), &sdrData[5], (TaskHandle_t *) &vTaskINA220_Handle, 0x45, FMC2_12V_DEVID },
{ TYPE_01, (void *) &SDR_FMC2_VADJ, sizeof(SDR_FMC2_VADJ), &sdrData[6], (TaskHandle_t *) &vTaskINA220_Handle, 0x42, FMC2_VADJ_DEVID },
{ TYPE_01, (void *) &SDR_FMC2_P3V3, sizeof(SDR_FMC2_P3V3), &sdrData[7], (TaskHandle_t *) &vTaskINA220_Handle, 0x44, FMC2_P3V3_DEVID },
/* Temperature Sensors */
{ TYPE_01, (void *) &SDR_LM75_1, sizeof(SDR_LM75_1), &sdrData[8], (TaskHandle_t *) &vTaskLM75_Handle, 0x4C, NO_DIAG },
{ TYPE_01, (void *) &SDR_LM75_2, sizeof(SDR_LM75_2), &sdrData[9], (TaskHandle_t *) &vTaskLM75_Handle, 0x4D, NO_DIAG }
};
#define SDR_ARRAY_LENGTH (sizeof(sensor_array) / sizeof(sensor_array[0]))
size_t sdr_get_size_by_type(SDR_TYPE type) size_t sdr_get_size_by_type(SDR_TYPE type)
{ {
...@@ -593,72 +50,75 @@ size_t sdr_get_size_by_type(SDR_TYPE type) ...@@ -593,72 +50,75 @@ size_t sdr_get_size_by_type(SDR_TYPE type)
} }
} }
size_t sdr_get_size_by_entry(int id) size_t sdr_get_size_by_entry(uint8_t id)
{ {
if (id >= SDR_ARRAY_LENGTH) { if (id >= sdr_count) {
return 0; return 0;
} }
return sdr_get_size_by_type(sensor_array[id].type); return sdr_get_size_by_type(sensor_array[id].sdr_type);
} }
void sensor_init( void ) void sensor_init( void )
{ {
hotswap_init(); hotswap_init();
LM75_init(); LM75_init();
#ifdef OLD_INA220
INA220_init();
#else
ina220_init(); ina220_init();
#endif
} }
static uint16_t reservationID; void sdr_init( void )
{
SemaphoreHandle_t semaphore_fru_control; sensor_array = pvPortMalloc( sizeof(sensor_t) );
uint8_t payload_ctrl_code; configASSERT(sensor_array);
void do_quiesced_init() /* Populate SDR Device Locator Record */
{ sensor_array[0].num = 0;
payload_ctrl_code = 0; sensor_array[0].sdr_type = TYPE_12;
semaphore_fru_control = xSemaphoreCreateBinary(); sensor_array[0].sdr = (void *) &SDR0;
} sensor_array[0].sdr_length = sizeof(SDR0);
sensor_array[0].task_handle = NULL;
sensor_array[0].diag_devID = NO_DIAG;
sensor_array[0].slave_addr = ipmb_addr;
sensor_array[0].entityinstance = 0x60 | ((ipmb_addr - 0x70) >> 1);
void do_quiesced(unsigned char ctlcode) sdr_count++;
{
payload_ctrl_code = ctlcode;
xSemaphoreGive(semaphore_fru_control);
} }
void sdr_init(uint8_t ipmiID) void sdr_insert_entry( SDR_TYPE type, void * sdr, TaskHandle_t *monitor_task, uint8_t diag_id, uint8_t slave_addr)
{ {
uint8_t i; uint8_t index = sdr_count;
for (i = 0; i < NUM_SDR; i++) { uint8_t sdr_len = sdr_get_size_by_type(type);
sensor_array[i].data->entityinstance = 0x60 | ((ipmiID - 0x70) >> 1);
sensor_array[i].data->ownerID = ipmiID; sensor_array = pvPortRealloc( sensor_array, sizeof(sensor_t)*(sdr_count+1) );
// @todo: remove this HOT_SWAP_SENSOR case, to enable first event sensor_array[index].num = index;
if (i == HOT_SWAP_SENSOR) { sensor_array[index].sdr_type = type;
sensor_array[i].data->comparator_status = HOT_SWAP_STATE_HANDLE_OPENED; sensor_array[index].sdr = sdr;
} else { sensor_array[index].sdr_length = sdr_len;
sensor_array[i].data->comparator_status = 0; sensor_array[index].task_handle = monitor_task;
sensor_array[i].data->readout_value = 0; sensor_array[index].diag_devID = diag_id;
} sensor_array[index].slave_addr = slave_addr;
} sensor_array[index].ownerID = ipmb_addr;
sensor_array[index].entityinstance = 0x60 | ((ipmb_addr - 0x70) >> 1);
sensor_array[index].readout_value = 0;
sensor_array[index].state = SENSOR_STATE_LOW_NON_REC;
sdr_count++;
} }
/******************************/ /******************************/
/* IPMI SDR Commands handlers */ /* IPMI SDR Commands handlers */
/******************************/ /******************************/
void ipmi_se_get_sdr_info(ipmi_msg *req, ipmi_msg *rsp) { IPMI_HANDLER(ipmi_se_get_sdr_info, NETFN_SE, IPMI_GET_DEVICE_SDR_INFO_CMD, ipmi_msg *req, ipmi_msg *rsp) {
int len = rsp->data_len; int len = rsp->data_len;
if (req->data_len == 0 || req->data[0] == 0) { if (req->data_len == 0 || req->data[0] == 0) {
rsp->data[len++] = NUM_SENSOR; /* Return number of sensors only */
rsp->data[len++] = sdr_count-1;
} else { } else {
rsp->data[len++] = NUM_SDR; /* Return number of SDR entries */
rsp->data[len++] = sdr_count;
} }
/* Static Sensor population and LUN 0 has sensors */ /* Static Sensor population and LUN 0 has sensors */
rsp->data[len++] = 0x01; // if dynamic additional 4 bytes required (see Table 20-2 Get Device SDR INFO Command rsp->data[len++] = 0x01; // if dynamic additional 4 bytes required (see Table 20-2 Get Device SDR INFO Command
...@@ -670,21 +130,48 @@ void ipmi_se_get_sdr_info(ipmi_msg *req, ipmi_msg *rsp) { ...@@ -670,21 +130,48 @@ void ipmi_se_get_sdr_info(ipmi_msg *req, ipmi_msg *rsp) {
* @brief Handler for "Set Event Receiver" command, as on IPMIv2 1.1 * @brief Handler for "Set Event Receiver" command, as on IPMIv2 1.1
* section 29.1. * section 29.1.
* *
* This handler should set (or reset) the address to which IPMI events * Set (or reset) the address to which IPMI events
* will be sent. Also, disable sending events if command 0xFF is received. * will be sent. Also, disable sending events if command 0xFF is received.
* *
* @param[in] req Incoming request to be handled and answered. * @param[in] req Incoming request to be handled and answered.
* *
* @return void * @return void
*/ */
void ipmi_se_set_receiver ( ipmi_msg *req, ipmi_msg *rsp) uint8_t event_receiver_addr = 0xFF;
uint8_t event_receiver_lun = 0x00;
IPMI_HANDLER(ipmi_se_set_event_reciever, NETFN_SE, IPMI_SET_EVENT_RECEIVER_CMD, ipmi_msg *req, ipmi_msg *rsp)
{ {
/** @todo: actually enable/disable sending events*/ /* Update the event receiver address (even if its 0xFF,
the checking will be done in check_sensor_event function) */
event_receiver_addr = req->data[0];
event_receiver_lun = req->data[1];
rsp->completion_code = IPMI_CC_OK; rsp->completion_code = IPMI_CC_OK;
rsp->data_len = 0; rsp->data_len = 0;
} }
void ipmi_se_get_sdr( ipmi_msg *req, ipmi_msg* rsp) /*!
* @brief Handler for "Get Event Receiver" command, as on IPMIv2 1.1
* section 29.1.
*
* Returns the previously set event receiver address and LUN
*
* @param[in] req Incoming request to be handled and answered.
*
* @return void
*/
IPMI_HANDLER(ipmi_se_get_event_reciever, NETFN_SE, IPMI_GET_EVENT_RECEIVER_CMD, ipmi_msg *req, ipmi_msg *rsp)
{
uint8_t len = 0;
rsp->data[len++] = event_receiver_addr;
rsp->data[len++] = event_receiver_lun;
rsp->completion_code = IPMI_CC_OK;
rsp->data_len = len;
}
IPMI_HANDLER(ipmi_se_get_sdr, NETFN_SE, IPMI_GET_DEVICE_SDR_CMD, ipmi_msg *req, ipmi_msg* rsp)
{ {
uint16_t recv_reserv_id = req->data[0] | (req->data[1] << 8); uint16_t recv_reserv_id = req->data[0] | (req->data[1] << 8);
uint16_t record_id = req->data[2] | (req->data[3] << 8); uint16_t record_id = req->data[2] | (req->data[3] << 8);
...@@ -711,11 +198,31 @@ void ipmi_se_get_sdr( ipmi_msg *req, ipmi_msg* rsp) ...@@ -711,11 +198,31 @@ void ipmi_se_get_sdr( ipmi_msg *req, ipmi_msg* rsp)
rsp->data[len++] = (record_id + 1) >> 8; /* next record ID */ rsp->data[len++] = (record_id + 1) >> 8; /* next record ID */
} }
uint8_t tmp_c; uint8_t tmp_c, index;
uint8_t * pSDR = (uint8_t*) sensor_array[record_id].sdr; uint8_t * pSDR = (uint8_t*) sensor_array[record_id].sdr;
uint8_t sdr_type = pSDR[3];
for (uint8_t i = 0; i < size; i++) { for (uint8_t i = 0; i < size; i++) {
tmp_c = pSDR[i+offset]; index = i + offset;
tmp_c = pSDR[index];
/* Return not-const data from SDR */
if (index == 0) {
tmp_c = record_id;
} else if (index == 5) {
tmp_c = sensor_array[record_id].ownerID;
} else if ( sdr_type == TYPE_01 || sdr_type == TYPE_02 ) {
if (index == 9) {
tmp_c = sensor_array[record_id].entityinstance;
}
if (index == 7) {
tmp_c = record_id;
}
} else if ( sdr_type == TYPE_11 || sdr_type == TYPE_12 ) {
if (index == 13) {
tmp_c = sensor_array[record_id].entityinstance;
}
}
rsp->data[len++] = tmp_c; rsp->data[len++] = tmp_c;
} }
...@@ -723,7 +230,7 @@ void ipmi_se_get_sdr( ipmi_msg *req, ipmi_msg* rsp) ...@@ -723,7 +230,7 @@ void ipmi_se_get_sdr( ipmi_msg *req, ipmi_msg* rsp)
rsp->completion_code = IPMI_CC_OK; rsp->completion_code = IPMI_CC_OK;
} }
void ipmi_se_reserve_device_sdr( ipmi_msg *req, ipmi_msg* rsp) { IPMI_HANDLER(ipmi_se_reserve_device_sdr, NETFN_SE, IPMI_RESERVE_DEVICE_SDR_REPOSITORY_CMD, ipmi_msg *req, ipmi_msg* rsp) {
int len = rsp->data_len; int len = rsp->data_len;
reservationID++; reservationID++;
...@@ -737,21 +244,452 @@ void ipmi_se_reserve_device_sdr( ipmi_msg *req, ipmi_msg* rsp) { ...@@ -737,21 +244,452 @@ void ipmi_se_reserve_device_sdr( ipmi_msg *req, ipmi_msg* rsp) {
rsp->completion_code = IPMI_CC_OK; rsp->completion_code = IPMI_CC_OK;
} }
void ipmi_se_get_sensor_reading( ipmi_msg *req, ipmi_msg* rsp) { IPMI_HANDLER(ipmi_se_get_sensor_reading, NETFN_SE, IPMI_GET_SENSOR_READING_CMD, ipmi_msg *req, ipmi_msg* rsp) {
int sensor_number = req->data[0]; int sensor_number = req->data[0];
int len = rsp->data_len; int len = rsp->data_len;
if (sensor_number >= NUM_SDR) { if (sensor_number > sdr_count) {
rsp->completion_code = IPMI_CC_REQ_DATA_NOT_PRESENT; rsp->completion_code = IPMI_CC_REQ_DATA_NOT_PRESENT;
rsp->data_len = 0; rsp->data_len = 0;
return; return;
} }
rsp->data[len++] = sensor_array[sensor_number].data->readout_value; if (*(sensor_array[sensor_number].task_handle) == vTaskHotSwap_Handle) {
/* Sensor scanning disabled */ rsp->data[len++] = 0x00;
rsp->data[len++] = 0x40; rsp->data[len++] = 0xC0;
rsp->data[len++] = sensor_array[sensor_number].data->comparator_status; /* Current State Mask */
rsp->data[len++] = sensor_array[sensor_number].readout_value;
} else {
rsp->data[len++] = sensor_array[sensor_number].readout_value;
rsp->data[len++] = 0x40;
/* Present threshold status */
/* TODO: Implement threshold reading */
rsp->data[len++] = 0xC0;
}
rsp->data_len = len; rsp->data_len = len;
rsp->completion_code = IPMI_CC_OK; rsp->completion_code = IPMI_CC_OK;
} }
void check_sensor_event( sensor_t * sensor )
{
/** Should be rewritten to be compliant with RTM management !! */
uint8_t ev = 0xFF;
uint8_t ev_type;
configASSERT(sensor);
SDR_type_01h_t * sdr = ( SDR_type_01h_t * ) sensor->sdr;
configASSERT(sdr);
if( sdr->hdr.rectype != TYPE_01 ) {
return;
}
/** Compare value with threshold */
switch(sensor->state) {
case SENSOR_STATE_HIGH_NON_REC:
if(sensor->signed_flag){
if(((int8_t)sensor->readout_value) <= (((int8_t)sdr->upper_nonrecover_thr) - (1+((int8_t)sdr->pos_thr_hysteresis)))){
if(sensor->asserted_event.upper_non_recoverable_go_high){
ev = IPMI_THRESHOLD_UNR_GH;
sensor->asserted_event.upper_non_recoverable_go_high = 0;
ev_type = DEASSERTION_EVENT;
}
sensor->state = SENSOR_STATE_HIGH_CRIT;
}
if(sensor->old_state != sensor->state && ((int8_t)sensor->readout_value) <= ((int8_t)sdr->upper_nonrecover_thr) && !sensor->asserted_event.upper_non_recoverable_go_low){
ev = IPMI_THRESHOLD_UNR_GL;
sensor->asserted_event.upper_non_recoverable_go_low = 1;
ev_type = ASSERTION_EVENT;
}
else if(((int8_t)sensor->readout_value) >= (((int8_t)sdr->upper_nonrecover_thr) + (1+((int8_t)sdr->neg_thr_hysteresis)))){
if(sensor->asserted_event.upper_non_recoverable_go_low){
ev = IPMI_THRESHOLD_UNR_GL;
sensor->asserted_event.upper_non_recoverable_go_low = 0;
}
}
}
else{
if(sensor->readout_value <= (sdr->upper_nonrecover_thr - (1+sdr->pos_thr_hysteresis))){
if(sensor->asserted_event.upper_non_recoverable_go_high){
ev = IPMI_THRESHOLD_UNR_GH;
sensor->asserted_event.upper_non_recoverable_go_high = 0;
ev_type = DEASSERTION_EVENT;
}
sensor->state = SENSOR_STATE_HIGH_CRIT;
}
if(sensor->old_state != sensor->state && sensor->readout_value <= sdr->upper_nonrecover_thr && !sensor->asserted_event.upper_non_recoverable_go_low){
ev = IPMI_THRESHOLD_UNR_GL;
sensor->asserted_event.upper_non_recoverable_go_low = 1;
ev_type = ASSERTION_EVENT;
}
else if(sensor->readout_value >= (sdr->upper_nonrecover_thr + (1+sdr->neg_thr_hysteresis))){
if(sensor->asserted_event.upper_non_recoverable_go_low){
ev = IPMI_THRESHOLD_UNR_GL;
sensor->asserted_event.upper_non_recoverable_go_low = 0;
ev_type = DEASSERTION_EVENT;
}
}
}
break;
case SENSOR_STATE_HIGH_CRIT:
if(sensor->signed_flag){
if(((int8_t)sensor->readout_value) >= ((int8_t)sdr->upper_nonrecover_thr)){
ev = IPMI_THRESHOLD_UNR_GH;
sensor->asserted_event.upper_non_recoverable_go_high = 1;
ev_type = ASSERTION_EVENT;
sensor->state = SENSOR_STATE_HIGH_NON_REC;
}
else if(((int8_t)sensor->readout_value) <= (((int8_t)sdr->upper_critical_thr) - (1+((int8_t)sdr->pos_thr_hysteresis)))){
if(sensor->asserted_event.upper_critical_go_high){
ev = IPMI_THRESHOLD_UC_GH;
sensor->asserted_event.upper_critical_go_high = 0;
ev_type = DEASSERTION_EVENT;
}
sensor->state = SENSOR_STATE_HIGH;
}
if(sensor->old_state != sensor->state && ((int8_t)sensor->readout_value) <= ((int8_t)sdr->upper_critical_thr) && !sensor->asserted_event.upper_critical_go_low){
ev = IPMI_THRESHOLD_UC_GL;
sensor->asserted_event.upper_critical_go_low = 1;
ev_type = ASSERTION_EVENT;
}
else if(((int8_t)sensor->readout_value) >= (((int8_t)sdr->upper_critical_thr) + (1+((int8_t)sdr->neg_thr_hysteresis)))){
if(sensor->asserted_event.upper_critical_go_low){
ev = IPMI_THRESHOLD_UC_GL;
sensor->asserted_event.upper_critical_go_low = 0;
ev_type = DEASSERTION_EVENT;
}
}
}
else{
if(sensor->readout_value >= sdr->upper_nonrecover_thr){
ev = IPMI_THRESHOLD_UNR_GH;
sensor->asserted_event.upper_non_recoverable_go_high = 1;
ev_type = ASSERTION_EVENT;
sensor->state = SENSOR_STATE_HIGH_NON_REC;
}
else if(sensor->readout_value <= (sdr->upper_critical_thr - (1+sdr->pos_thr_hysteresis))){
if(sensor->asserted_event.upper_critical_go_high){
ev = IPMI_THRESHOLD_UC_GH;
sensor->asserted_event.upper_critical_go_high = 0;
ev_type = DEASSERTION_EVENT;
}
sensor->state = SENSOR_STATE_HIGH;
}
if(sensor->old_state != sensor->state && sensor->readout_value <= sdr->upper_critical_thr && !sensor->asserted_event.upper_critical_go_low){
ev = IPMI_THRESHOLD_UC_GL;
sensor->asserted_event.upper_critical_go_low = 1;
ev_type = ASSERTION_EVENT;
}
else if(sensor->readout_value >= (sdr->upper_critical_thr + (1+sdr->neg_thr_hysteresis))){
if(sensor->asserted_event.upper_critical_go_low){
ev = IPMI_THRESHOLD_UC_GL;
sensor->asserted_event.upper_critical_go_low = 0;
ev_type = DEASSERTION_EVENT;
}
}
}
break;
case SENSOR_STATE_HIGH:
if(sensor->signed_flag){
if(((int8_t)sensor->readout_value) >= ((int8_t)sdr->upper_critical_thr)){
ev = IPMI_THRESHOLD_UC_GH;
sensor->asserted_event.upper_critical_go_high = 1;
ev_type = ASSERTION_EVENT;
sensor->state = SENSOR_STATE_HIGH_CRIT;
}
else if(((int8_t)sensor->readout_value) <= (((int8_t)sdr->upper_noncritical_thr) - (1+((int8_t)sdr->pos_thr_hysteresis)))){
if(sensor->asserted_event.upper_non_critical_go_high){
ev = IPMI_THRESHOLD_UNC_GH;
sensor->asserted_event.upper_non_critical_go_high = 0;
ev_type = DEASSERTION_EVENT;
}
sensor->state = SENSOR_STATE_NORMAL;
}
if(sensor->old_state != sensor->state && ((int8_t)sensor->readout_value) <= ((int8_t)sdr->upper_noncritical_thr) && !sensor->asserted_event.upper_non_critical_go_low){
ev = IPMI_THRESHOLD_UNC_GL;
sensor->asserted_event.upper_non_critical_go_low = 1;
ev_type = ASSERTION_EVENT;
}
else if(((int8_t)sensor->readout_value) >= (((int8_t)sdr->upper_noncritical_thr) + (1+((int8_t)sdr->neg_thr_hysteresis)))){
if(sensor->asserted_event.upper_non_critical_go_low){
ev = IPMI_THRESHOLD_UNC_GL;
sensor->asserted_event.upper_non_critical_go_low = 0;
ev_type = DEASSERTION_EVENT;
}
}
}
else{
if(sensor->readout_value >= sdr->upper_critical_thr){
ev = IPMI_THRESHOLD_UC_GH;
sensor->asserted_event.upper_critical_go_high = 1;
ev_type = ASSERTION_EVENT;
sensor->state = SENSOR_STATE_HIGH_CRIT;
}
else if(sensor->readout_value <= (sdr->upper_noncritical_thr - (1+sdr->pos_thr_hysteresis))){
if(sensor->asserted_event.upper_non_critical_go_high){
ev = IPMI_THRESHOLD_UNC_GH;
sensor->asserted_event.upper_non_critical_go_high = 0;
ev_type = DEASSERTION_EVENT;
}
sensor->state = SENSOR_STATE_NORMAL;
}
if(sensor->old_state != sensor->state && sensor->readout_value <= sdr->upper_noncritical_thr && !sensor->asserted_event.upper_non_critical_go_low){
ev = IPMI_THRESHOLD_UNC_GL;
sensor->asserted_event.upper_non_critical_go_low = 1;
ev_type = ASSERTION_EVENT;
}
else if(sensor->readout_value >= (sdr->upper_noncritical_thr + (1+sdr->neg_thr_hysteresis))){
if(sensor->asserted_event.upper_non_critical_go_low){
ev = IPMI_THRESHOLD_UNC_GL;
sensor->asserted_event.upper_non_critical_go_low = 0;
ev_type = DEASSERTION_EVENT;
}
}
}
break;
case SENSOR_STATE_NORMAL:
if(sensor->signed_flag){
if(((int8_t)sensor->readout_value) >= ((int8_t)sdr->upper_noncritical_thr)){
ev = IPMI_THRESHOLD_UNC_GH;
sensor->asserted_event.upper_non_critical_go_high = 1;
ev_type = ASSERTION_EVENT;
sensor->state = SENSOR_STATE_HIGH;
}
else if(((int8_t)sensor->readout_value) <= ((int8_t)sdr->lower_noncritical_thr)){
ev = IPMI_THRESHOLD_LNC_GL;
ev_type = ASSERTION_EVENT;
sensor->state = SENSOR_STATE_LOW;
}
}
else{
if(sensor->readout_value >= sdr->upper_noncritical_thr){
ev = IPMI_THRESHOLD_UNC_GH;
sensor->asserted_event.upper_non_critical_go_high = 1;
ev_type = ASSERTION_EVENT;
sensor->state = SENSOR_STATE_HIGH;
}
else if(sensor->readout_value <= sdr->lower_noncritical_thr){
ev = IPMI_THRESHOLD_LNC_GL;
ev_type = ASSERTION_EVENT;
sensor->state = SENSOR_STATE_LOW;
}
}
break;
case SENSOR_STATE_LOW:
if(sensor->signed_flag){
if(((int8_t)sensor->readout_value) <= ((int8_t)sdr->lower_critical_thr)){
ev = IPMI_THRESHOLD_LC_GH;
sensor->asserted_event.lower_critical_go_high = 1;
ev_type = ASSERTION_EVENT;
sensor->state = SENSOR_STATE_LOW_CRIT;
}
else if(((int8_t)sensor->readout_value) >= (((int8_t)sdr->lower_noncritical_thr) + (1+((int8_t)sdr->pos_thr_hysteresis)))){
if(sensor->asserted_event.upper_non_critical_go_high){
ev = IPMI_THRESHOLD_LNC_GH;
sensor->asserted_event.lower_non_critical_go_high = 0;
ev_type = DEASSERTION_EVENT;
}
sensor->state = SENSOR_STATE_NORMAL;
}
if(sensor->old_state != sensor->state && ((int8_t)sensor->readout_value) >= ((int8_t)sdr->lower_noncritical_thr)){
ev = IPMI_THRESHOLD_LNC_GL;
sensor->asserted_event.lower_non_critical_go_low = 1;
ev_type = ASSERTION_EVENT;
}
else if(((int8_t)sensor->readout_value) <= (((int8_t)sdr->lower_noncritical_thr) - (1+((int8_t)sdr->neg_thr_hysteresis)))){
if(sensor->asserted_event.lower_non_critical_go_low){
ev = IPMI_THRESHOLD_LNC_GL;
sensor->asserted_event.lower_non_critical_go_low = 0;
ev_type = DEASSERTION_EVENT;
}
}
}
else{
if(sensor->readout_value <= sdr->lower_critical_thr){
ev = IPMI_THRESHOLD_LC_GH;
sensor->asserted_event.lower_critical_go_high = 1;
ev_type = ASSERTION_EVENT;
sensor->state = SENSOR_STATE_LOW_CRIT;
}
else if(sensor->readout_value >= (sdr->lower_noncritical_thr + (1+sdr->pos_thr_hysteresis))){
if(sensor->asserted_event.upper_non_critical_go_high){
ev = IPMI_THRESHOLD_LNC_GH;
sensor->asserted_event.lower_non_critical_go_high = 0;
ev_type = DEASSERTION_EVENT;
}
sensor->state = SENSOR_STATE_NORMAL;
}
if(sensor->old_state != sensor->state && sensor->readout_value >= sdr->lower_noncritical_thr){
ev = IPMI_THRESHOLD_LNC_GL;
sensor->asserted_event.lower_non_critical_go_low = 1;
ev_type = ASSERTION_EVENT;
}
else if(sensor->readout_value <= (sdr->lower_noncritical_thr - (1+sdr->neg_thr_hysteresis))){
if(sensor->asserted_event.lower_non_critical_go_low){
ev = IPMI_THRESHOLD_LNC_GL;
sensor->asserted_event.lower_non_critical_go_low = 0;
ev_type = DEASSERTION_EVENT;
}
}
}
break;
case SENSOR_STATE_LOW_CRIT:
if(sensor->signed_flag){
if(((int8_t)sensor->readout_value) <= ((int8_t)sdr->lower_nonrecover_thr)){
ev = IPMI_THRESHOLD_LNR_GH;
sensor->asserted_event.lower_non_recorverable_go_high = 1;
ev_type = ASSERTION_EVENT;
sensor->state = SENSOR_STATE_LOW_NON_REC;
}
else if(((int8_t)sensor->readout_value) >= (((int8_t)sdr->lower_critical_thr) + (1+((int8_t)sdr->pos_thr_hysteresis)))){
if(sensor->asserted_event.upper_critical_go_high){
ev = IPMI_THRESHOLD_LC_GH;
sensor->asserted_event.lower_critical_go_high = 0;
ev_type = DEASSERTION_EVENT;
}
sensor->state = SENSOR_STATE_LOW;
}
if(sensor->old_state != sensor->state && ((int8_t)sensor->readout_value) >= ((int8_t)sdr->lower_critical_thr)){
ev = IPMI_THRESHOLD_LC_GL;
sensor->asserted_event.lower_critical_go_low = 1;
ev_type = ASSERTION_EVENT;
}
else if(((int8_t)sensor->readout_value) <= (((int8_t)sdr->lower_critical_thr) - (1+((int8_t)sdr->neg_thr_hysteresis)))){
if(sensor->asserted_event.lower_critical_go_low){
ev = IPMI_THRESHOLD_LC_GL;
sensor->asserted_event.lower_critical_go_low = 0;
ev_type = DEASSERTION_EVENT;
}
}
}
else{
if(sensor->readout_value <= sdr->lower_nonrecover_thr){
ev = IPMI_THRESHOLD_LNR_GH;
sensor->asserted_event.lower_non_recorverable_go_high = 1;
ev_type = ASSERTION_EVENT;
sensor->state = SENSOR_STATE_LOW_NON_REC;
}
else if(sensor->readout_value >= (sdr->lower_critical_thr + (1+sdr->pos_thr_hysteresis))){
if(sensor->asserted_event.upper_critical_go_high){
ev = IPMI_THRESHOLD_LC_GH;
sensor->asserted_event.lower_critical_go_high = 0;
ev_type = DEASSERTION_EVENT;
}
sensor->state = SENSOR_STATE_LOW;
}
if(sensor->old_state != sensor->state && sensor->readout_value >= sdr->lower_critical_thr){
ev = IPMI_THRESHOLD_LC_GL;
sensor->asserted_event.lower_critical_go_low = 1;
ev_type = ASSERTION_EVENT;
}
else if(sensor->readout_value <= (sdr->lower_critical_thr - (1+sdr->neg_thr_hysteresis))){
if(sensor->asserted_event.lower_critical_go_low){
ev = IPMI_THRESHOLD_LC_GL;
sensor->asserted_event.lower_critical_go_low = 0;
ev_type = DEASSERTION_EVENT;
}
}
}
break;
case SENSOR_STATE_LOW_NON_REC:
if(sensor->signed_flag){
if(((int8_t)sensor->readout_value) >= (((int8_t)sdr->lower_nonrecover_thr) + (1+((int8_t)sdr->pos_thr_hysteresis)))){
if(sensor->asserted_event.upper_non_recoverable_go_high){
ev = IPMI_THRESHOLD_LNR_GH;
sensor->asserted_event.lower_non_recorverable_go_high = 0;
ev_type = DEASSERTION_EVENT;
}
sensor->state = SENSOR_STATE_LOW_CRIT;
}
if(sensor->old_state != sensor->state && ((int8_t)sensor->readout_value) >= ((int8_t)sdr->lower_nonrecover_thr)){
ev = IPMI_THRESHOLD_LNR_GL;
sensor->asserted_event.lower_non_recoverable_go_low = 1;
ev_type = ASSERTION_EVENT;
}
else if(((int8_t)sensor->readout_value) <= (((int8_t)sdr->lower_critical_thr) - (1+((int8_t)sdr->neg_thr_hysteresis)))){
if(sensor->asserted_event.lower_non_recoverable_go_low){
ev = IPMI_THRESHOLD_LNR_GL;
sensor->asserted_event.lower_non_recoverable_go_low = 0;
ev_type = DEASSERTION_EVENT;
}
}
}
else{
if(sensor->readout_value >= (sdr->lower_nonrecover_thr + (1+sdr->pos_thr_hysteresis))){
if(sensor->asserted_event.upper_non_recoverable_go_high){
ev = IPMI_THRESHOLD_LNR_GH;
sensor->asserted_event.lower_non_recorverable_go_high = 0;
ev_type = DEASSERTION_EVENT;
}
sensor->state = SENSOR_STATE_LOW_CRIT;
}
if(sensor->old_state != sensor->state && sensor->readout_value >= sdr->lower_nonrecover_thr){
ev = IPMI_THRESHOLD_LNR_GL;
sensor->asserted_event.lower_non_recoverable_go_low = 1;
ev_type = ASSERTION_EVENT;
}
else if(sensor->readout_value <= (sdr->lower_critical_thr - (1+sdr->neg_thr_hysteresis))){
if(sensor->asserted_event.lower_non_recoverable_go_low){
ev = IPMI_THRESHOLD_LNR_GL;
sensor->asserted_event.lower_non_recoverable_go_low = 0;
ev_type = DEASSERTION_EVENT;
}
}
}
break;
}
sensor->old_state = sensor->state;
if ((ev != 0xFF) && (event_receiver_addr != 0xFF)) {
ipmi_event_send(sensor, ev_type, &ev, 1);
}
}
/* Management Controller Device Locator Record 37.9 SDR Type 12h */
const SDR_type_12h_t SDR0 = {
.hdr.recID_LSB = 0x00,
.hdr.recID_MSB = 0x00,
.hdr.SDRversion = 0x51, /* IPMI protocol version */
.hdr.rectype = TYPE_12, /* record type: device locator record */
.hdr.reclength = sizeof(SDR_type_12h_t) - sizeof(SDR_entry_hdr_t),
/* record key bytes */
.slaveaddr = 0x00,
.chnum = 0x00,
.power_notification_global_init = 0x04,
.device_cap = 0x3b,
.reserved[0] = 0x00,
.reserved[1] = 0x00,
.reserved[2] = 0x00,
.entityID = 0xC1,
.entityinstance = 0x00,
.OEM = 0x00,
.IDtypelen = 0xc0 | STR_SIZE(STR(TARGET_BOARD_NAME)), /* 8 bit ASCII, number of bytes */
.IDstring = STR(TARGET_BOARD_NAME)
};
/* /*
* sdr.c * openMMC -- Open Source modular IPM Controller firmware
*
* AFCIPMI --
* *
* Copyright (C) 2015 Piotr Miedzik <P.Miedzik@gsi.de> * Copyright (C) 2015 Piotr Miedzik <P.Miedzik@gsi.de>
* Copyright (C) 2015-2016 Henrique Silva <henrique.silva@lnls.br>
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
...@@ -17,55 +16,60 @@ ...@@ -17,55 +16,60 @@
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* @license GPL-3.0+ <http://spdx.org/licenses/GPL-3.0+>
*/ */
#ifndef IPMI_SDR_H_ #ifndef SDR_H_
#define IPMI_SDR_H_ #define SDR_H_
#include "ipmb.h" #include "ipmb.h"
#define NUM_SENSOR 9 /* Number of sensors */ #define NUM_SENSOR 17 /* Number of sensors */
#define NUM_SDR (NUM_SENSOR+1) /* Number of SDRs */ #define NUM_SDR (NUM_SENSOR+1) /* Number of SDRs */
#define HOT_SWAP_SENSOR 1
#define NUM_SDR_FMC2_12V 2
#define NUM_SDR_FMC2_VADJ 3
#define NUM_SDR_FMC2_3V3 4
#define NUM_SDR_FMC1_12V 5
#define NUM_SDR_FMC1_VADJ 6
#define NUM_SDR_FMC1_3V3 7
#define NUM_SDR_LM75_1 8
#define NUM_SDR_LM75_2 9
#define NUM_SDR_LM75_3 10
#define NUM_SDR_LM75_4 11
/* Sensor Types */ /* Sensor Types */
#define SENSOR_TYPE_TEMPERATURE 0x01 #define SENSOR_TYPE_TEMPERATURE 0x01
#define SENSOR_TYPE_VOLTAGE 0x02 #define SENSOR_TYPE_VOLTAGE 0x02
#define SENSOR_TYPE_CURRENT 0x03 #define SENSOR_TYPE_CURRENT 0x03
#define SENSOR_TYPE_FAN 0x04 #define SENSOR_TYPE_FAN 0x04
#define SENSOR_TYPE_WATCHDOG 0x23 #define SENSOR_TYPE_WATCHDOG 0x23
#define SENSOR_TYPE_VERSION_CHANGE 0x2B #define SENSOR_TYPE_VERSION_CHANGE 0x2B
#define SENSOR_TYPE_HOT_SWAP 0xF2 #define SENSOR_TYPE_HOT_SWAP 0xF2
/* Module handle sensor status */ /* Assertion Event Codes */
#define HOT_SWAP_CLOSED 0x00 #define ASSERTION_EVENT 0x00
#define HOT_SWAP_OPENED 0x01 #define DEASSERTION_EVENT 0x80
#define HOT_SWAP_QUIESCED 0x02
/* Sensor States */
#define HOT_SWAP_STATE_HANDLE_CLOSED (1 << 0) #define SENSOR_STATE_NORMAL 0x00 // temperature is in normal range
#define HOT_SWAP_STATE_HANDLE_OPENED (1 << 1) #define SENSOR_STATE_LOW 0x01 // temperature is below lower non critical
#define HOT_SWAP_STATE_QUIESCED (1 << 2) #define SENSOR_STATE_LOW_CRIT 0x02 // temperature is below lower critical
#define HOT_SWAP_STATE_BP_SDOWN (1 << 3) #define SENSOR_STATE_LOW_NON_REC 0x04 // temperature is below lower non recoverable
#define HOT_SWAP_STATE_BP_FAIL (1 << 4) #define SENSOR_STATE_HIGH 0x08 // temperature is higher upper non critical
#define HOT_SWAP_STATE_URTM_PRSENT (1 << 5) #define SENSOR_STATE_HIGH_CRIT 0x10 // temperature is higher upper critical
#define HOT_SWAP_STATE_URTM_ABSENT (1 << 6) #define SENSOR_STATE_HIGH_NON_REC 0x20 // temperature is higher high non recoverable
#define HOT_SWAP_STATE_URTM_COMPATIBLE (1 << 7)
#define HOT_SWAP_STATE_URTM_INCOMPATIBLE (1 << 0)
/* IPMI Sensor Events */
#define IPMI_THRESHOLD_LNC_GL 0x00 // lower non critical going low
#define IPMI_THRESHOLD_LNC_GH 0x01 // lower non critical going high
#define IPMI_THRESHOLD_LC_GL 0x02 // lower critical going low
#define IPMI_THRESHOLD_LC_GH 0x03 // lower critical going HIGH
#define IPMI_THRESHOLD_LNR_GL 0x04 // lower non recoverable going low
#define IPMI_THRESHOLD_LNR_GH 0x05 // lower non recoverable going high
#define IPMI_THRESHOLD_UNC_GL 0x06 // upper non critical going low
#define IPMI_THRESHOLD_UNC_GH 0x07 // upper non critical going high
#define IPMI_THRESHOLD_UC_GL 0x08 // upper critical going low
#define IPMI_THRESHOLD_UC_GH 0x09 // upper critical going HIGH
#define IPMI_THRESHOLD_UNR_GL 0x0A // upper non recoverable going low
#define IPMI_THRESHOLD_UNR_GH 0x0B // upper non recoverable going high
typedef enum { typedef enum {
TYPE_01 = 0x1, TYPE_01 = 0x1,
TYPE_02 = 0x2, TYPE_02 = 0x2,
TYPE_11 = 0x11,
TYPE_12 = 0x12 TYPE_12 = 0x12
} SDR_TYPE; } SDR_TYPE;
...@@ -169,37 +173,48 @@ typedef struct { ...@@ -169,37 +173,48 @@ typedef struct {
} SDR_type_12h_t; } SDR_type_12h_t;
typedef struct { typedef struct {
uint8_t ownerID; uint8_t num;
uint8_t entityID; SDR_TYPE sdr_type;
uint8_t entityinstance;
uint16_t readout_value;
uint8_t comparator_status;
void * sensor_info;
} sensor_data_entry_t;
typedef struct {
SDR_TYPE type;
void * sdr; void * sdr;
uint8_t sdr_length; uint8_t sdr_length;
sensor_data_entry_t * data;
TaskHandle_t * task_handle;
uint8_t slave_addr;
uint8_t diag_devID; uint8_t diag_devID;
uint8_t state;
uint8_t old_state;
uint16_t readout_value;
uint8_t slave_addr;
uint8_t signed_flag;
uint8_t ownerID; /* This field is repeated here because its value is assigned during initialization, so it can't be const */
uint8_t entityinstance; /* This field is repeated here because its value is assigned during initialization, so it can't be const */
TaskHandle_t * task_handle;
struct {
uint16_t upper_non_recoverable_go_high:1;
uint16_t upper_non_recoverable_go_low:1;
uint16_t upper_critical_go_high:1;
uint16_t upper_critical_go_low:1;
uint16_t upper_non_critical_go_high:1;
uint16_t upper_non_critical_go_low:1;
uint16_t lower_non_recorverable_go_high:1;
uint16_t lower_non_recoverable_go_low:1;
uint16_t lower_critical_go_high:1;
uint16_t lower_critical_go_low:1;
uint16_t lower_non_critical_go_high:1;
uint16_t lower_non_critical_go_low:1;
} asserted_event;
} sensor_t; } sensor_t;
extern sensor_data_entry_t sdrData[NUM_SDR]; extern sensor_t *sensor_array;
extern const sensor_t const sensor_array[NUM_SDR]; extern uint8_t sdr_count;
const SDR_type_12h_t SDR0;
#define GET_SENSOR_TYPE(sensor) ((SDR_type_01h_t *)sensor->sdr)->sensortype
void ipmi_se_get_sdr( ipmi_msg *req, ipmi_msg* rsp); #define GET_EVENT_TYPE_CODE(n) ((SDR_type_01h_t *)sensor->sdr)->event_reading_type
void ipmi_se_get_sensor_reading( ipmi_msg *req, ipmi_msg* rsp);
void ipmi_se_get_sdr_info( ipmi_msg *req, ipmi_msg* rsp);
void ipmi_se_reserve_device_sdr( ipmi_msg *req, ipmi_msg* rsp);
//void ipmi_se_set_receiver ( ipmi_msg *req, ipmi_msg *rsp );
void initializeDCDC(); void initializeDCDC( void );
void do_quiesced_init(); void sdr_init( void );
void do_quiesced(unsigned char ctlcode);
void sdr_init(uint8_t ipmiID);
void sensor_init( void ); void sensor_init( void );
void sdr_insert_entry( SDR_TYPE type, void * sdr, TaskHandle_t *monitor_task, uint8_t diag_id, uint8_t slave_addr );
void check_sensor_event( sensor_t * sensor );
#endif #endif
#Sensors
set(SENSOR_PATH ${CMAKE_CURRENT_SOURCE_DIR})
include_directories(${SENSOR_PATH})
if (";${TARGET_MODULES};" MATCHES ";HOTSWAP_SENSOR;")
set(PROJ_SRCS ${PROJ_SRCS} ${SENSOR_PATH}/hotswap.c )
set(MODULES_FLAGS "${MODULES_FLAGS} -DMODULE_HOTSWAP")
endif()
if (";${TARGET_MODULES};" MATCHES ";TEMPERATURE_SENSOR;")
set(PROJ_SRCS ${PROJ_SRCS} ${SENSOR_PATH}/lm75.c)
set(MODULES_FLAGS "${MODULES_FLAGS} -DMODULE_TEMPERATURE_SENSOR")
endif()
if (";${TARGET_MODULES};" MATCHES ";VOLTAGE_SENSOR;")
set(PROJ_SRCS ${PROJ_SRCS} ${SENSOR_PATH}/ina220.c)
#INA220 SDR is in a different source because it's too large and would polute the ina220.c
set(PROJ_SRCS ${PROJ_SRCS} ${SENSOR_PATH}/ina220_sdr.c)
set(MODULES_FLAGS "${MODULES_FLAGS} -DMODULE_VOLTAGE_SENSOR")
endif()
if (";${TARGET_MODULES};" MATCHES ";CURRENT_SENSOR;")
set(PROJ_SRCS ${PROJ_SRCS} ${SENSOR_PATH}/ina220.c)
set(PROJ_SRCS ${PROJ_SRCS} ${SENSOR_PATH}/ina220_sdr.c)
set(MODULES_FLAGS "${MODULES_FLAGS} -DMODULE_CURRENT_SENSOR")
endif()
set(PROJ_SRCS ${PROJ_SRCS} ${SENSOR_PATH} PARENT_SCOPE)
set(PROJ_HDRS ${PROJ_HDRS} ${SENSOR_PATH} PARENT_SCOPE)
set(MODULES_FLAGS "${MODULES_FLAGS}" PARENT_SCOPE)
/* /*
* hotswap.c * openMMC -- Open Source modular IPM Controller firmware
* *
* AFCIPMI -- * Copyright (C) 2015-2016 Henrique Silva <henrique.silva@lnls.br>
*
* Copyright (C) 2015
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
...@@ -17,6 +15,8 @@ ...@@ -17,6 +15,8 @@
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* @license GPL-3.0+ <http://spdx.org/licenses/GPL-3.0+>
*/ */
#include "FreeRTOS.h" #include "FreeRTOS.h"
...@@ -29,6 +29,7 @@ ...@@ -29,6 +29,7 @@
#include "task_priorities.h" #include "task_priorities.h"
#include "ipmi.h" #include "ipmi.h"
#include "led.h" #include "led.h"
#include "utils.h"
#define HOTSWAP_POLL #define HOTSWAP_POLL
//#define HOTSWAP_INT //#define HOTSWAP_INT
...@@ -44,30 +45,46 @@ void EINT3_IRQHandler( void ) ...@@ -44,30 +45,46 @@ void EINT3_IRQHandler( void )
/* Simple debouncing routine */ /* Simple debouncing routine */
/* If the last interruption happened in the last 200ms, this one is only a bounce, ignore it and wait for the next interruption */ /* If the last interruption happened in the last 200ms, this one is only a bounce, ignore it and wait for the next interruption */
if (getTickDifference(current_time, last_time) < DEBOUNCE_TIME){ if (getTickDifference(current_time, last_time) < DEBOUNCE_TIME) {
/*! @todo Clear all the active interrupts tied to EXT3, not only the hot swap */
Chip_GPIOINT_ClearIntStatus(LPC_GPIOINT, HOT_SWAP_HANDLE_PORT, (1 << HOT_SWAP_HANDLE_PIN));
return; return;
} }
/* Checks if the interrupt occurred in Port2 */ /* Checks if the interrupt occurred in Port2 */
if (Chip_GPIOINT_IsIntPending(LPC_GPIOINT, HOT_SWAP_HANDLE_PORT)) { if (!Chip_GPIOINT_IsIntPending(LPC_GPIOINT, HOT_SWAP_HANDLE_PORT)) {
/*! @bug If any other GPIO interruption is enabled in Port 2, it'll trigger the hotswap messaging */ /* Clear interrupt pending bit */
asm("nop");
if ( gpio_read_pin(HOT_SWAP_HANDLE_PORT, HOT_SWAP_HANDLE_PIN) == 0 ) {
hotswap_state = HOT_SWAP_STATE_HANDLE_CLOSED;
} else {
hotswap_state = HOT_SWAP_STATE_HANDLE_OPENED;
}
xTaskNotifyFromISR( vTaskHotSwap_Handle, hotswap_state, eSetValueWithOverwrite, &xHigherPriorityTaskWoken );
Chip_GPIOINT_ClearIntStatus(LPC_GPIOINT, HOT_SWAP_HANDLE_PORT, (1 << HOT_SWAP_HANDLE_PIN)); Chip_GPIOINT_ClearIntStatus(LPC_GPIOINT, HOT_SWAP_HANDLE_PORT, (1 << HOT_SWAP_HANDLE_PIN));
return;
}
if ((Chip_GPIOINT_GetStatusRising(LPC_GPIOINT, HOT_SWAP_HANDLE_PORT) >> HOT_SWAP_HANDLE_PIN) & 1) {
hotswap_state = HOT_SWAP_STATE_HANDLE_OPENED;
} else if ((Chip_GPIOINT_GetStatusFalling(LPC_GPIOINT, HOT_SWAP_HANDLE_PORT) >> HOT_SWAP_HANDLE_PIN) & 1) {
hotswap_state = HOT_SWAP_STATE_HANDLE_CLOSED;
} }
/* Notify the Hotswap task about the handle event */
xTaskNotifyFromISR( vTaskHotSwap_Handle, hotswap_state, eSetValueWithOverwrite, &xHigherPriorityTaskWoken );
/* Clear interrupt pending bit */
Chip_GPIOINT_ClearIntStatus(LPC_GPIOINT, HOT_SWAP_HANDLE_PORT, (1 << HOT_SWAP_HANDLE_PIN));
portYIELD_FROM_ISR( xHigherPriorityTaskWoken ); portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
} }
#endif #endif
static uint8_t hotswap_get_handle_status( void )
{
if (gpio_read_pin(HOT_SWAP_HANDLE_PORT, HOT_SWAP_HANDLE_PIN)) {
return HOTSWAP_MODULE_HANDLE_OPEN_MASK;
} else {
return HOTSWAP_MODULE_HANDLE_CLOSED_MASK;
}
}
static SDR_type_02h_t * hotswap_pSDR;
static sensor_t * hotswap_sensor;
void hotswap_init( void ) void hotswap_init( void )
{ {
#ifdef HOTSWAP_INT #ifdef HOTSWAP_INT
...@@ -76,16 +93,18 @@ void hotswap_init( void ) ...@@ -76,16 +93,18 @@ void hotswap_init( void )
/* Enable Rising and Falling edge interruption on Hot Swap pin */ /* Enable Rising and Falling edge interruption on Hot Swap pin */
Chip_GPIOINT_SetIntFalling(LPC_GPIOINT, HOT_SWAP_HANDLE_PORT, (1 << HOT_SWAP_HANDLE_PIN)); Chip_GPIOINT_SetIntFalling(LPC_GPIOINT, HOT_SWAP_HANDLE_PORT, (1 << HOT_SWAP_HANDLE_PIN));
Chip_GPIOINT_SetIntRising(LPC_GPIOINT, HOT_SWAP_HANDLE_PORT, (1 <<HOT_SWAP_HANDLE_PIN)); Chip_GPIOINT_SetIntRising(LPC_GPIOINT, HOT_SWAP_HANDLE_PORT, (1 << HOT_SWAP_HANDLE_PIN));
/* Configure the IRQ */ /* Configure the IRQ */
NVIC_SetPriority( EINT3_IRQn, configMAX_SYSCALL_INTERRUPT_PRIORITY - 1); irq_set_priority( EINT3_IRQn, configMAX_SYSCALL_INTERRUPT_PRIORITY - 1);
NVIC_EnableIRQ( EINT3_IRQn ); irq_enable( EINT3_IRQn );
#endif #endif
/* Create Hot Swap task */ /* Create Hot Swap task */
xTaskCreate( vTaskHotSwap, "Hot Swap", 200, (void *) NULL, tskHOTSWAP_PRIORITY, &vTaskHotSwap_Handle); xTaskCreate( vTaskHotSwap, "Hot Swap", 200, (void *) NULL, tskHOTSWAP_PRIORITY, &vTaskHotSwap_Handle);
for ( uint8_t i = 0; i < NUM_SDR; i++ ) { sdr_insert_entry( TYPE_02, (void *) &SDR_HOT_SWAP, &vTaskHotSwap_Handle, 0, 0 );
for ( uint8_t i = 0; i < sdr_count; i++ ) {
/* Check if the handle pointer is not NULL */ /* Check if the handle pointer is not NULL */
if (sensor_array[i].task_handle == NULL) { if (sensor_array[i].task_handle == NULL) {
...@@ -97,7 +116,10 @@ void hotswap_init( void ) ...@@ -97,7 +116,10 @@ void hotswap_init( void )
continue; continue;
} }
sensor_array[i].data->comparator_status |= HOT_SWAP_STATE_HANDLE_OPENED; hotswap_sensor = &sensor_array[i];
hotswap_pSDR = (SDR_type_02h_t *) sensor_array[i].sdr;
hotswap_sensor->readout_value = hotswap_get_handle_status();
} }
} }
...@@ -105,9 +127,8 @@ void vTaskHotSwap( void *Parameters ) ...@@ -105,9 +127,8 @@ void vTaskHotSwap( void *Parameters )
{ {
ipmi_msg pmsg; ipmi_msg pmsg;
uint8_t data_len = 0; uint8_t data_len = 0;
uint8_t i; uint8_t evt_msg;
SDR_type_01h_t *pSDR = NULL;
sensor_data_entry_t * pDATA;
#ifdef HOTSWAP_INT #ifdef HOTSWAP_INT
uint8_t new_flag; uint8_t new_flag;
uint8_t init_state; uint8_t init_state;
...@@ -131,8 +152,15 @@ void vTaskHotSwap( void *Parameters ) ...@@ -131,8 +152,15 @@ void vTaskHotSwap( void *Parameters )
TickType_t xLastWakeTime; TickType_t xLastWakeTime;
const TickType_t xFrequency = 50; const TickType_t xFrequency = 50;
/* Initialise the xLastWakeTime variable with the current time. */ /* Override Blue LED state so that if the handle is closed when the MMC is starting, the LED remains in the correct state */
xLastWakeTime = xTaskGetTickCount(); if ( gpio_read_pin(HOT_SWAP_HANDLE_PORT, HOT_SWAP_HANDLE_PIN) == 0 ) {
LED_update( LED_BLUE, &LED_Off_Activity );
} else {
LED_update( LED_BLUE, &LED_On_Activity );
}
/* Initialise the xLastWakeTime variable with the current time. */
xLastWakeTime = xTaskGetTickCount();
#endif #endif
...@@ -140,86 +168,95 @@ void vTaskHotSwap( void *Parameters ) ...@@ -140,86 +168,95 @@ void vTaskHotSwap( void *Parameters )
#ifdef HOTSWAP_INT #ifdef HOTSWAP_INT
new_flag = ulTaskNotifyTake(pdTRUE, portMAX_DELAY); new_flag = ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
/* Find hotswap sensor in SDR table */ evt_msg = new_flag >> 1;
for ( i = 0; i < NUM_SDR; i++ ) {
/* Check if the handle pointer is not NULL */
if (sensor_array[i].task_handle == NULL) {
continue;
}
/* Check if this task should update the selected SDR */
if ( *(sensor_array[i].task_handle) != xTaskGetCurrentTaskHandle() ) {
continue;
}
pSDR = (SDR_type_01h_t *) sensor_array[i].sdr;
pDATA = sensor_array[i].data;
data_len = 0;
pmsg.dest_LUN = 0;
pmsg.netfn = NETFN_SE;
pmsg.cmd = IPMI_PLATFORM_EVENT_CMD;
pmsg.data[data_len++] = 0x04;
pmsg.data[data_len++] = 0xf2;
pmsg.data[data_len++] = pSDR->sensornum;
pmsg.data[data_len++] = 0x6f;
pmsg.data[data_len++] = (new_flag >> 1); // hot swap state
pmsg.data_len = data_len;
if (ipmb_send_request( &pmsg ) == ipmb_error_success) {
/* Update the SDR */
pDATA->comparator_status = (pDATA->comparator_status & 0xFC) | new_flag;
} else {
xTaskNotifyGive(xTaskGetCurrentTaskHandle());
vTaskDelay(20);
}
break;
if ( ipmi_event_send(hotswap_sensor, ASSERTION_EVENT, &evt_msg, sizeof(evt_msg)) == ipmb_error_success) {
/* Update the SDR */
hotswap_sensor->readout_value = (hotswap_sensor->readout_value & 0xFC) | new_flag;
} else {
/* If the message fails to be sent, unblock itself to try again */
xTaskNotifyGive(xTaskGetCurrentTaskHandle());
} }
#endif #endif
#ifdef HOTSWAP_POLL #ifdef HOTSWAP_POLL
vTaskDelayUntil( &xLastWakeTime, xFrequency ); vTaskDelayUntil( &xLastWakeTime, xFrequency );
/* Find hotswap sensor in SDR table */ new_state = hotswap_get_handle_status();
for ( i = 0; i < NUM_SDR; i++ ) {
if( new_state == old_state ) {
/* Check if the handle pointer is not NULL */ continue;
if (sensor_array[i].task_handle == NULL) {
continue;
}
/* Check if this task should update the selected SDR */
if ( *(sensor_array[i].task_handle) != xTaskGetCurrentTaskHandle() ) {
continue;
}
new_state = gpio_read_pin(HOT_SWAP_HANDLE_PORT, HOT_SWAP_HANDLE_PIN);
if( new_state == old_state ) {
continue;
}
pSDR = (SDR_type_01h_t *) sensor_array[i].sdr;
pDATA = sensor_array[i].data;
data_len = 0;
pmsg.dest_LUN = 0;
pmsg.netfn = NETFN_SE;
pmsg.cmd = IPMI_PLATFORM_EVENT_CMD;
pmsg.data[data_len++] = 0x04;
pmsg.data[data_len++] = 0xf2;
pmsg.data[data_len++] = pSDR->sensornum;
pmsg.data[data_len++] = 0x6f;
pmsg.data[data_len++] = new_state; // hot swap state
pmsg.data_len = data_len;
if (ipmb_send_request( &pmsg ) == ipmb_error_success) {
/* Update the SDR */
pDATA->readout_value = (pDATA->readout_value & 0xFC) | new_state;
old_state = new_state;
}
} }
if ( hotswap_send_event( new_state ) == ipmb_error_success )
{
hotswap_set_mask_bit( new_state );
old_state = new_state;
}
#endif #endif
} }
} }
ipmb_error hotswap_send_event( uint8_t evt )
{
uint8_t evt_msg;
evt_msg = evt >> 1;
return ipmi_event_send( hotswap_sensor, ASSERTION_EVENT, &evt_msg, sizeof( evt_msg ) );
}
void hotswap_clear_mask_bit( uint8_t mask )
{
if ( hotswap_sensor ) {
hotswap_sensor->readout_value &= ~mask;
}
}
void hotswap_set_mask_bit( uint8_t mask )
{
if ( hotswap_sensor ) {
hotswap_sensor->readout_value |= mask;
}
}
/* AMC Hot-Swap sensor SDR */
const SDR_type_02h_t SDR_HOT_SWAP = {
.hdr.recID_LSB = 0x00, /* Filled by sdr_insert_entry() */
.hdr.recID_MSB = 0x00,
.hdr.SDRversion = 0x51,
.hdr.rectype = TYPE_02,
.hdr.reclength = sizeof(SDR_type_02h_t) - sizeof(SDR_entry_hdr_t),
.ownerID = 0x00, /* i2c address, -> SDR_Init */
.ownerLUN = 0x00, /* sensor owner LUN */
.sensornum = 0x00, /* Filled by sdr_insert_entry() */
/* record body bytes */
.entityID = 0xC1, /* entity id: AMC Module */
.entityinstance = 0x00, /* entity instance -> SDR_Init */
.sensorinit = 0x03, /* init: event generation + scanning enabled */
.sensorcap = 0xc1, /* capabilities: auto re-arm,*/
.sensortype = SENSOR_TYPE_HOT_SWAP, /* sensor type: HOT SWAP*/
.event_reading_type = 0x6f, /* sensor reading*/
.assertion_event_mask = { 0x00, /* LSB assert event mask: 3 bit value */
0x00 }, /* MSB assert event mask */
.deassertion_event_mask = { 0x00, /* LSB deassert event mask: 3 bit value */
0x00 }, /* MSB deassert event mask */
.readable_threshold_mask = 0x00, /* LSB: readable Threshold mask: no thresholds are readable: */
.settable_threshold_mask = 0x00, /* MSB: setable Threshold mask: no thresholds are setable: */
.sensor_units_1 = 0xc0, /* sensor units 1 : Does not return analog reading*/
.sensor_units_2 = 0x00, /* sensor units 2 :*/
.sensor_units_3 = 0x00, /* sensor units 3 :*/
.record_sharing[0] = 0x00,
.record_sharing[1] = 0x00,
.pos_thr_hysteresis = 0x00, /* positive going Threshold hysteresis value */
.neg_thr_hysteresis = 0x00, /* negative going Threshold hysteresis value */
.reserved1 = 0x00, /* reserved */
.reserved2 = 0x00, /* reserved */
.reserved3 = 0x00, /* reserved */
.OEM = 0x00, /* OEM reserved */
.IDtypelen = 0xc0 | STR_SIZE("HOTSWAP HANDLE"), /* 8 bit ASCII, number of bytes */
.IDstring = "HOTSWAP HANDLE" /* sensor string */
};
/* /*
* hotswap.c * openMMC -- Open Source modular IPM Controller firmware
* *
* AFCIPMI -- * Copyright (C) 2015-2016 Henrique Silva <henrique.silva@lnls.br>
*
* Copyright (C) 2015
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
...@@ -17,12 +15,35 @@ ...@@ -17,12 +15,35 @@
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* @license GPL-3.0+ <http://spdx.org/licenses/GPL-3.0+>
*/ */
#define DEBOUNCE_TIME 250 #define DEBOUNCE_TIME 250
extern TaskHandle_t vTaskHotSwap_Handle; /* Module handle sensor status */
#define HOT_SWAP_STATE_HANDLE_CLOSED 0x00
#define HOT_SWAP_STATE_HANDLE_OPENED 0x01
#define HOT_SWAP_STATE_QUIESCED 0x02
#define HOT_SWAP_STATE_BP_FAIL 0x03
#define HOT_SWAP_STATE_BP_SDOWN 0x04
#define HOT_SWAP_STATE_URTM_PRSENT 0x05
#define HOT_SWAP_STATE_URTM_ABSENT 0x06
#define HOT_SWAP_STATE_URTM_COMPATIBLE 0x07
#define HOT_SWAP_STATE_URTM_INCOMPATIBLE 0x08
#define HOTSWAP_MODULE_HANDLE_CLOSED_MASK 0x01
#define HOTSWAP_MODULE_HANDLE_OPEN_MASK 0x02
#define HOTSWAP_QUIESCED_MASK 0x04
#define HOTSWAP_BACKEND_PWR_FAILURE_MASK 0x08
#define HOTSWAP_BACKEND_PWR_SHUTDOWN_MASK 0x10
TaskHandle_t vTaskHotSwap_Handle;
extern const SDR_type_02h_t SDR_HOT_SWAP;
extern TickType_t getTickDifference(TickType_t current_time, TickType_t start_time);
void vTaskHotSwap( void *Parameters ); void vTaskHotSwap( void *Parameters );
void hotswap_init( void ); void hotswap_init( void );
ipmb_error hotswap_send_event( uint8_t evt );
void hotswap_set_mask_bit( uint8_t mask );
void hotswap_clear_mask_bit( uint8_t mask );
/* /*
* AFCIPMI -- * openMMC -- Open Source modular IPM Controller firmware
* *
* Copyright (C) 2015 Henrique Silva <henrique.silva@lnls.br> * Copyright (C) 2015-2016 Henrique Silva <henrique.silva@lnls.br>
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
...@@ -15,6 +15,8 @@ ...@@ -15,6 +15,8 @@
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* @license GPL-3.0+ <http://spdx.org/licenses/GPL-3.0+>
*/ */
/*! /*!
...@@ -25,134 +27,36 @@ ...@@ -25,134 +27,36 @@
* @brief DCDCs Voltage reading using INA220 sensor * @brief DCDCs Voltage reading using INA220 sensor
*/ */
/* FreeRTOS Includes */
#include "FreeRTOS.h" #include "FreeRTOS.h"
#include "task.h" #include "task.h"
/* Project Includes */
#include "port.h" #include "port.h"
#include "sdr.h" #include "sdr.h"
#include "task_priorities.h" #include "task_priorities.h"
#include "board_version.h" #include "board_version.h"
#include "payload.h" #include "payload.h"
#include "ina220.h" #include "ina220.h"
#include "fpga_spi.h"
#ifdef OLD_INA220
void vTaskINA220( void * Parameters )
{
TickType_t xLastWakeTime;
/* Task will run every 100ms */
const TickType_t xFrequency = INA220_UPDATE_RATE / portTICK_PERIOD_MS;
uint8_t i2c_bus_id;
uint8_t i;
SDR_type_01h_t *pSDR;
sensor_data_entry_t * pDATA;
/* Initialise the xLastWakeTime variable with the current time. */
xLastWakeTime = xTaskGetTickCount();
for ( ;; ) {
/* Update all [voltage sensors readings */
for ( i = 0; i < NUM_SDR; i++ ) {
/* Check if the handle pointer is not NULL */
if (sensor_array[i].task_handle == NULL) {
continue;
}
/* Check if this task should update the selected SDR */
if ( *(sensor_array[i].task_handle) != xTaskGetCurrentTaskHandle() ) {
continue;
}
pSDR = (SDR_type_01h_t *) sensor_array[i].sdr;
pDATA = sensor_array[i].data;
/* Try to gain the I2C bus */
if (afc_i2c_take_by_busid(I2C_BUS_CPU_ID, &i2c_bus_id, (TickType_t)100) == pdFALSE) {
continue;
}
/* Update sensor reading on SDR */
pDATA->readout_value = INA220_readVolt( i2c_bus_id, sensor_array[i].slave_addr, true );
/* Take different action for each sensor */
switch ((pSDR->hdr.recID_MSB << 8)|(pSDR->hdr.recID_LSB)) {
case NUM_SDR_FMC2_12V:
/* Compare reading with sensor threshold levels */
if (pDATA->readout_value > pSDR->lower_noncritical_thr) {
payload_send_message(PAYLOAD_MESSAGE_P12GOOD);
} else if (pDATA->readout_value < pSDR->lower_critical_thr) {
payload_send_message(PAYLOAD_MESSAGE_P12GOODn);
}
break;
default:
break;
}
afc_i2c_give( i2c_bus_id );
}
vTaskDelayUntil( &xLastWakeTime, xFrequency );
}
}
uint16_t INA220_readVolt(I2C_ID_T i2c, uint8_t address, bool raw)
{
uint8_t ch[2];
uint16_t tmpVal = 0;
xI2CMasterWriteRead(i2c, address, INA220_BUS_REG, ch, 2);
tmpVal = (0x1fE0 & (ch[0] << 5)) | (0x1f & (ch[1] >> 3));
if (raw == false) {
tmpVal = tmpVal * 4;
}
return tmpVal/16;
}
void INA220_init( void )
{
#define INA_CFG
uint8_t i, j;
uint8_t i2c_bus_id;
xTaskCreate( vTaskINA220, "INA220", configMINIMAL_STACK_SIZE, (void *) NULL, tskINA220SENSOR_PRIORITY, &vTaskINA220_Handle);
#ifdef INA_CFG
for ( j = 0, i = 0; i < NUM_SDR && j < MAX_INA220_COUNT; i++, j++ ) {
if ( *(sensor_array[i].task_handle) != vTaskINA220_Handle ) {
continue;
}
if (afc_i2c_take_by_busid(I2C_BUS_CPU_ID, &i2c_bus_id, (TickType_t) 50) == pdFALSE) {
continue;
}
uint8_t cmd[3] = {0x00, 0x01, 0x9F};
portENABLE_INTERRUPTS();
xI2CMasterWrite(i2c_bus_id, sensor_array[i].slave_addr, cmd, sizeof(cmd));
portDISABLE_INTERRUPTS();
afc_i2c_give( i2c_bus_id );
}
#endif
}
#else
const t_ina220_config ina220_cfg = { const t_ina220_config ina220_cfg = {
.config_default = INA220_CONFIG_DEFAULT, .config_reg_default.cfg_struct = { .bus_voltage_range = INA220_16V_SCALE_RANGE,
.pga_gain = INA220_PGA_GAIN_40MV,
.bus_adc_resolution = INA220_RES_SAMPLES_12BIT,
.shunt_adc_resolution = INA220_RES_SAMPLES_12BIT,
.mode = INA220_MODE_SHUNT_BUS_CONT },
.calibration_factor = 40960000, .calibration_factor = 40960000,
.calibration_reg = 0xA000, /* Calculated using INA220EVM software from Texas Instruments */
.registers = INA220_REGISTERS, .registers = INA220_REGISTERS,
.shunt_div = 100, .shunt_div = 100,
.bus_voltage_shift = 3, .bus_voltage_shift = 3,
.bus_voltage_lsb = 4000, .bus_voltage_lsb = 4, /* in mV */
.power_lsb = 20000, .power_lsb = 20
}; };
static t_ina220_data ina220_data[MAX_INA220_COUNT]; static t_ina220_data ina220_data[MAX_INA220_COUNT];
void vTaskINA220( void *Parameters ) void vTaskINA220( void *Parameters )
{ {
uint8_t i; uint8_t i;
...@@ -160,9 +64,7 @@ void vTaskINA220( void *Parameters ) ...@@ -160,9 +64,7 @@ void vTaskINA220( void *Parameters )
TickType_t xLastWakeTime; TickType_t xLastWakeTime;
/* Task will run every 100ms */ /* Task will run every 100ms */
const TickType_t xFrequency = INA220_UPDATE_RATE / portTICK_PERIOD_MS; const TickType_t xFrequency = INA220_UPDATE_RATE / portTICK_PERIOD_MS;
sensor_t * ina220_sensor;
SDR_type_01h_t *pSDR;
sensor_data_entry_t * pDATA;
t_ina220_data * data_ptr; t_ina220_data * data_ptr;
/* Initialise the xLastWakeTime variable with the current time. */ /* Initialise the xLastWakeTime variable with the current time. */
...@@ -171,60 +73,46 @@ void vTaskINA220( void *Parameters ) ...@@ -171,60 +73,46 @@ void vTaskINA220( void *Parameters )
for (;;) { for (;;) {
/* Read all registers from the INA220s */ /* Read all registers from the INA220s */
for ( i = 0; i < MAX_INA220_COUNT; i++) { for ( i = 0; i < MAX_INA220_COUNT; i++) {
ina220_readall( &ina220_data[i] ); ina220_readall( &ina220_data[i] );
}
ina220_sensor = ina220_data[i].sensor;
for ( i = 0; i < NUM_SDR; i++ ) { data_ptr = &ina220_data[i];
/* Update their SDR */
/* Check if the handle pointer is not NULL */
if (sensor_array[i].task_handle == NULL) {
continue;
}
/* Check if this task should update the selected SDR */ switch ((GET_SENSOR_TYPE(ina220_sensor))) {
if ( *(sensor_array[i].task_handle) != xTaskGetCurrentTaskHandle() ) { case SENSOR_TYPE_VOLTAGE:
continue; ina220_sensor->readout_value = (data_ptr->regs[INA220_BUS_VOLTAGE] >> data_ptr->config->bus_voltage_shift)/16;
break;
case SENSOR_TYPE_CURRENT:
/* Current in mA */
ina220_sensor->readout_value = data_ptr->regs[INA220_CURRENT]/32;
break;
default:
/* Shunt voltage and power not implemented */
break;
} }
pSDR = sensor_array[i].sdr; /* Check for threshold events */
pDATA = sensor_array[i].data; check_sensor_event(ina220_sensor);
data_ptr = pDATA->sensor_info;
switch (pSDR->sensortype) { if( ina220_sensor->sdr == &SDR_FMC1_12V ) {
case SENSOR_TYPE_VOLTAGE: /* Check if the Payload power is in an acceptable zone */
pDATA->readout_value = ((data_ptr->regs[INA220_BUS_VOLTAGE] >> data_ptr->config->bus_voltage_shift) * data_ptr->config->bus_voltage_lsb) / 100000; SDR_type_01h_t * ina220_sdr = ( SDR_type_01h_t * ) ina220_sensor->sdr;
break; if ( ( ina220_sensor->readout_value >= (ina220_sdr->lower_critical_thr ) ) &&
case SENSOR_TYPE_CURRENT: ( ina220_sensor->readout_value <= (ina220_sdr->upper_critical_thr ) ) ) {
/* Current in mA */
pDATA->readout_value = data_ptr->regs[INA220_CURRENT];
break;
default:
/* Shunt voltage and power not implemented */
break;
}
/* Maybe implement a callback function for each sensor type, and assign on initialization, in a more generic way for all sensors */
switch ((pSDR->hdr.recID_MSB << 8)|(pSDR->hdr.recID_LSB)) {
case NUM_SDR_FMC2_12V:
/* Compare reading with sensor threshold levels */
if (pDATA->readout_value > pSDR->lower_noncritical_thr) {
payload_send_message(PAYLOAD_MESSAGE_P12GOOD); payload_send_message(PAYLOAD_MESSAGE_P12GOOD);
} else if (pDATA->readout_value < pSDR->lower_critical_thr) { } else {
payload_send_message(PAYLOAD_MESSAGE_P12GOODn); payload_send_message(PAYLOAD_MESSAGE_P12GOODn);
} }
break;
default:
break;
} }
vTaskDelayUntil( &xLastWakeTime, xFrequency ); vTaskDelayUntil( &xLastWakeTime, xFrequency );
} }
} }
} }
uint8_t ina220_config(uint8_t i2c_id, t_ina220_data * data) uint8_t ina220_config(uint8_t i2c_id, t_ina220_data * data)
{ {
uint8_t i2c_bus = I2C1; uint8_t i2c_bus;
data->config = &ina220_cfg; data->config = &ina220_cfg;
data->i2c_id = i2c_id; data->i2c_id = i2c_id;
...@@ -233,20 +121,20 @@ uint8_t ina220_config(uint8_t i2c_id, t_ina220_data * data) ...@@ -233,20 +121,20 @@ uint8_t ina220_config(uint8_t i2c_id, t_ina220_data * data)
} else { } else {
return -1; return -1;
} }
data->curr_config = data->config->config_default; data->curr_reg_config = data->config->config_reg_default;
/* Change to 'afc_i2c_take_by_chipid', which is more generic */ /* @todo Change to 'i2c_take_by_chipid', which is more generic */
if( afc_i2c_take_by_busid( I2C_BUS_CPU_ID, &(i2c_bus), (TickType_t) 100) == pdFALSE ) { if( i2c_take_by_busid( I2C_BUS_CPU_ID, &(i2c_bus), (TickType_t) 10) == pdFALSE ) {
return -1; return -1;
} }
uint8_t cfg_buff[3] = { INA220_CONFIG, ( data->curr_config >> 8 ), ( data->curr_config & 0xFFFF ) }; uint8_t cfg_buff[3] = { INA220_CONFIG, ( data->curr_reg_config.cfg_word >> 8) , ( data->curr_reg_config.cfg_word & 0xFFFF) };
portENABLE_INTERRUPTS(); portENABLE_INTERRUPTS();
xI2CMasterWrite( i2c_bus, data->i2c_id, cfg_buff, sizeof(cfg_buff)/sizeof(cfg_buff[0]) ); xI2CMasterWrite( i2c_bus, data->i2c_id, cfg_buff, sizeof(cfg_buff)/sizeof(cfg_buff[0]) );
portDISABLE_INTERRUPTS(); portDISABLE_INTERRUPTS();
afc_i2c_give(i2c_bus); i2c_give(i2c_bus);
return 0; return 0;
} }
...@@ -256,14 +144,14 @@ uint16_t ina220_readvalue( t_ina220_data * data, uint8_t reg ) ...@@ -256,14 +144,14 @@ uint16_t ina220_readvalue( t_ina220_data * data, uint8_t reg )
uint8_t i2c_bus; uint8_t i2c_bus;
uint8_t val[2]; uint8_t val[2];
/*! @todo: Change to 'afc_i2c_take_by_chipid', which is more generic */ /*! @todo: Change to 'i2c_take_by_chipid', which is more generic */
if( afc_i2c_take_by_busid( I2C_BUS_CPU_ID, &(i2c_bus), (TickType_t) 10) == pdFALSE ) { if( i2c_take_by_busid( I2C_BUS_CPU_ID, &(i2c_bus), (TickType_t) 10) == pdFALSE ) {
return -1; return -1;
} }
xI2CMasterWriteRead( i2c_bus, data->i2c_id, reg, &val[0], sizeof(val)/sizeof(val[0]) ); xI2CMasterWriteRead( i2c_bus, data->i2c_id, reg, &val[0], sizeof(val)/sizeof(val[0]) );
afc_i2c_give( i2c_bus ); i2c_give( i2c_bus );
return ( (val[0] << 8) | (val[1]) ); return ( (val[0] << 8) | (val[1]) );
} }
...@@ -276,42 +164,75 @@ void ina220_readall( t_ina220_data * data ) ...@@ -276,42 +164,75 @@ void ina220_readall( t_ina220_data * data )
} }
} }
Bool ina220_calibrate( t_ina220_data * data )
void ina220_sdr_init ( TaskHandle_t handle )
{ {
uint8_t i, j; uint8_t i2c_bus;
t_ina220_data * data_ptr; uint16_t cal = data->config->calibration_reg;
uint8_t cal_reg[3] = { INA220_CALIBRATION, (cal >> 8), (cal & 0xFFFF) };
while (i < MAX_INA220_COUNT) { /*! @todo: Change to 'i2c_take_by_chipid', which is more generic */
for ( j = 0; j < NUM_SDR; j++ ) { if( i2c_take_by_busid( I2C_BUS_CPU_ID, &(i2c_bus), (TickType_t) 10) == pdFALSE ) {
/* Update their SDR */ return false;
/* Check if the handle pointer is not NULL */ }
if (sensor_array[j].task_handle == NULL) {
continue;
}
/* Check if this task should update the selected SDR */ portENABLE_INTERRUPTS();
if ( *(sensor_array[j].task_handle) != handle ) { xI2CMasterWrite( i2c_bus, data->i2c_id, &cal_reg[0], sizeof(cal_reg)/sizeof(cal_reg[0]) );
continue; portDISABLE_INTERRUPTS();
}
sensor_array[j].data->sensor_info = &ina220_data[i]; i2c_give( i2c_bus );
data_ptr = (t_ina220_data *) sensor_array[j].data->sensor_info;
data_ptr->i2c_id = sensor_array[j].slave_addr;
ina220_config( data_ptr->i2c_id, data_ptr );
i++;
}
}
return true;
} }
void ina220_init( void ) void ina220_init( void )
{ {
uint8_t i, j;
i = 0;
xTaskCreate( vTaskINA220, "INA220", 400, (void *) NULL, tskINA220SENSOR_PRIORITY, &vTaskINA220_Handle); xTaskCreate( vTaskINA220, "INA220", 400, (void *) NULL, tskINA220SENSOR_PRIORITY, &vTaskINA220_Handle);
configASSERT(vTaskINA220_Handle); /* FMC1 Voltage */
sdr_insert_entry( TYPE_01, (void *) &SDR_FMC1_12V, &vTaskINA220_Handle, FMC1_12V_DEVID, 0x45 );
sdr_insert_entry( TYPE_01, (void *) &SDR_FMC1_VADJ, &vTaskINA220_Handle, FMC1_VADJ_DEVID, 0x41 );
sdr_insert_entry( TYPE_01, (void *) &SDR_FMC1_P3V3, &vTaskINA220_Handle, FMC1_P3V3_DEVID, 0x43 );
/* FMC1 Current */
sdr_insert_entry( TYPE_01, (void *) &SDR_FMC1_12V_CURR, &vTaskINA220_Handle, FMC1_12V_CURR_DEVID, 0x45 );
sdr_insert_entry( TYPE_01, (void *) &SDR_FMC1_VADJ_CURR, &vTaskINA220_Handle, FMC1_VADJ_CURR_DEVID, 0x41 );
sdr_insert_entry( TYPE_01, (void *) &SDR_FMC1_P3V3_CURR, &vTaskINA220_Handle, FMC1_P3V3_CURR_DEVID, 0x43 );
/* FMC2 Voltage */
sdr_insert_entry( TYPE_01, (void *) &SDR_FMC2_12V, &vTaskINA220_Handle, FMC2_12V_DEVID, 0x40 );
sdr_insert_entry( TYPE_01, (void *) &SDR_FMC2_VADJ, &vTaskINA220_Handle, FMC2_VADJ_DEVID, 0x42 );
sdr_insert_entry( TYPE_01, (void *) &SDR_FMC2_P3V3, &vTaskINA220_Handle, FMC2_P3V3_DEVID, 0x44 );
/* FMC2 Current */
sdr_insert_entry( TYPE_01, (void *) &SDR_FMC2_12V_CURR, &vTaskINA220_Handle, FMC2_12V_CURR_DEVID, 0x40 );
sdr_insert_entry( TYPE_01, (void *) &SDR_FMC2_VADJ_CURR, &vTaskINA220_Handle, FMC2_VADJ_CURR_DEVID, 0x42 );
sdr_insert_entry( TYPE_01, (void *) &SDR_FMC2_P3V3_CURR, &vTaskINA220_Handle, FMC2_P3V3_CURR_DEVID, 0x44 );
for ( j = 0; j < sdr_count; j++ ) {
/* Update their SDR */
/* Check if the handle pointer is not NULL */
if (sensor_array[j].task_handle == NULL) {
continue;
}
ina220_sdr_init(vTaskINA220_Handle); /* Check if this task should update the selected SDR */
} if ( *(sensor_array[j].task_handle) != vTaskINA220_Handle ) {
continue;
}
if (i < MAX_INA220_COUNT ) {
ina220_data[i].sensor = &sensor_array[j];
ina220_data[i].i2c_id = sensor_array[j].slave_addr;
ina220_config( ina220_data[i].i2c_id, &ina220_data[i] );
ina220_calibrate( &ina220_data[i] );
ina220_data[i].sensor->signed_flag = 0;
#endif if ((GET_SENSOR_TYPE(ina220_data[i].sensor)) == SENSOR_TYPE_CURRENT ) {
ina220_data[i].sensor->signed_flag = 1;
}
i++;
}
}
}
/* /*
* AFCIPMI -- * openMMC -- Open Source modular IPM Controller firmware
* *
* Copyright (C) 2015 Henrique Silva <henrique.silva@lnls.br> * Copyright (C) 2015-2016 Henrique Silva <henrique.silva@lnls.br>
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
...@@ -15,14 +15,16 @@ ...@@ -15,14 +15,16 @@
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* @license GPL-3.0+ <http://spdx.org/licenses/GPL-3.0+>
*/ */
/*! /*!
* @file lm75.h * @file ina220.h
* @author Henrique Silva <henrique.silva@lnls.br>, LNLS * @author Henrique Silva <henrique.silva@lnls.br>, LNLS
* @date September 2015 * @date September 2015
* *
* @brief Definitions for LM75 I2C Temperature Sensor * @brief Definitions for INA220 Current/Voltage/Power Sensor
*/ */
#ifndef INA220_H_ #ifndef INA220_H_
...@@ -31,7 +33,7 @@ ...@@ -31,7 +33,7 @@
#include "FreeRTOS.h" #include "FreeRTOS.h"
#include "port.h" #include "port.h"
#define MAX_INA220_COUNT 6 #define MAX_INA220_COUNT 12
#define INA220_UPDATE_RATE 100 #define INA220_UPDATE_RATE 100
/* common register definitions */ /* common register definitions */
...@@ -45,8 +47,39 @@ ...@@ -45,8 +47,39 @@
/* register count */ /* register count */
#define INA220_REGISTERS 6 #define INA220_REGISTERS 6
/* settings - depend on use case */ /* Scale range values */
#define INA220_CONFIG_DEFAULT 0x399F /* PGA=8 */ #define INA220_16V_SCALE_RANGE 0x00
#define INA220_32V_SCALE_RANGE 0x01
/* PGA gain */
#define INA220_PGA_GAIN_40MV 0x00
#define INA220_PGA_GAIN_80MV 0x01
#define INA220_PGA_GAIN_160MV 0x02
#define INA220_PGA_GAIN_320MV 0x03
/* ADC Resolution/Averaging */
#define INA220_RES_SAMPLES_9BIT 0x0
#define INA220_RES_SAMPLES_10BIT 0x1
#define INA220_RES_SAMPLES_11BIT 0x2
#define INA220_RES_SAMPLES_12BIT 0x3
#define INA220_RES_SAMPLES_2SMP 0x9
#define INA220_RES_SAMPLES_4SMP 0xA
#define INA220_RES_SAMPLES_8SMP 0xB
#define INA220_RES_SAMPLES_16SMP 0xC
#define INA220_RES_SAMPLES_32SMP 0xD
#define INA220_RES_SAMPLES_64SMP 0xE
#define INA220_RES_SAMPLES_128SMP 0xF
/* Operating modes */
#define INA220_MODE_POWER_DOWN 0x0
#define INA220_MODE_SHUNT_TRIG 0x1
#define INA220_MODE_BUS_TRIG 0x2
#define INA220_MODE_SHUNT_BUS_TRIG 0x3
#define INA220_MODE_ADC_OFF 0x4
#define INA220_MODE_SHUNT_CONT 0x5
#define INA220_MODE_BUS_CONT 0x6
#define INA220_MODE_SHUNT_BUS_CONT 0x7
/* worst case is 68.10 ms (~14.6Hz, ina219) */ /* worst case is 68.10 ms (~14.6Hz, ina219) */
#define INA220_CONVERSION_RATE 15 #define INA220_CONVERSION_RATE 15
...@@ -54,9 +87,33 @@ ...@@ -54,9 +87,33 @@
#define INA220_RSHUNT_DEFAULT 10000 #define INA220_RSHUNT_DEFAULT 10000
typedef union {
struct {
#ifdef BF_MS_FIRST
uint16_t mode:3;
uint16_t shunt_adc_resolution:4;
uint16_t bus_adc_resolution:4;
uint16_t pga_gain:2;
uint16_t bus_voltage_range:1;
uint16_t reserved:1;
uint16_t reset:1;
#else
uint16_t reset:1;
uint16_t reserved:1;
uint16_t bus_voltage_range:1;
uint16_t pga_gain:2;
uint16_t bus_adc_resolution:4;
uint16_t shunt_adc_resolution:4;
uint16_t mode:3;
#endif
} cfg_struct;
uint16_t cfg_word;
} t_ina220_config_reg;
typedef struct { typedef struct {
uint16_t config_default; t_ina220_config_reg config_reg_default;
uint32_t calibration_factor; uint32_t calibration_factor;
uint16_t calibration_reg;
uint8_t registers; uint8_t registers;
uint8_t shunt_div; uint8_t shunt_div;
uint8_t bus_voltage_shift; uint8_t bus_voltage_shift;
...@@ -66,25 +123,36 @@ typedef struct { ...@@ -66,25 +123,36 @@ typedef struct {
typedef struct { typedef struct {
uint8_t i2c_id; uint8_t i2c_id;
const t_ina220_config *config; sensor_t * sensor;
const t_ina220_config * config;
uint32_t rshunt; uint32_t rshunt;
uint16_t curr_config; t_ina220_config_reg curr_reg_config;
uint16_t regs[INA220_REGISTERS]; uint16_t regs[INA220_REGISTERS];
} t_ina220_data; } t_ina220_data;
extern TaskHandle_t vTaskINA220_Handle; TaskHandle_t vTaskINA220_Handle;
/* INA220 SDR List */
extern const SDR_type_01h_t SDR_FMC1_VADJ;
extern const SDR_type_01h_t SDR_FMC1_12V;
extern const SDR_type_01h_t SDR_FMC1_P3V3;
extern const SDR_type_01h_t SDR_FMC1_VADJ_CURR;
extern const SDR_type_01h_t SDR_FMC1_12V_CURR;
extern const SDR_type_01h_t SDR_FMC1_P3V3_CURR;
extern const SDR_type_01h_t SDR_FMC2_VADJ;
extern const SDR_type_01h_t SDR_FMC2_12V;
extern const SDR_type_01h_t SDR_FMC2_P3V3;
extern const SDR_type_01h_t SDR_FMC2_VADJ_CURR;
extern const SDR_type_01h_t SDR_FMC2_12V_CURR;
extern const SDR_type_01h_t SDR_FMC2_P3V3_CURR;
#ifdef OLD_INA220
void INA220_init( void );
uint16_t INA220_readVolt(uint8_t i2c, uint8_t address, bool raw);
#else
uint8_t ina220_config(uint8_t i2c_id, t_ina220_data * data); uint8_t ina220_config(uint8_t i2c_id, t_ina220_data * data);
Bool ina220_calibrate( t_ina220_data * data );
uint16_t ina220_readvalue( t_ina220_data * data, uint8_t reg ); uint16_t ina220_readvalue( t_ina220_data * data, uint8_t reg );
uint16_t ina220_readvalue( t_ina220_data * data, uint8_t reg ); uint16_t ina220_readvalue( t_ina220_data * data, uint8_t reg );
void ina220_readall( t_ina220_data * data ); void ina220_readall( t_ina220_data * data );
void ina220_sdr_init ( TaskHandle_t handle ); void ina220_sdr_init ( TaskHandle_t handle );
void ina220_init( void ); void ina220_init( void );
#endif
void vTaskINA220( void* Parameters ); void vTaskINA220( void* Parameters );
......
/*
* openMMC -- Open Source modular IPM Controller firmware
*
* Copyright (C) 2015-2016 Henrique Silva <henrique.silva@lnls.br>
*
* 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 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* @license GPL-3.0+ <http://spdx.org/licenses/GPL-3.0+>
*/
#include "sdr.h"
#include "utils.h"
#define SDR_FMC1_12V_ID "FMC1 +12V"
#define SDR_FMC1_VADJ_ID "FMC1 VADJ"
#define SDR_FMC1_P3V3_ID "FMC1 +3.3V"
#define SDR_FMC1_VADJ_CURR_ID "FMC1 +12V Curr"
#define SDR_FMC1_12V_CURR_ID "FMC1 VADJ Curr"
#define SDR_FMC1_P3V3_CURR_ID "FMC1 +3.3V Curr"
#define SDR_FMC2_12V_ID "FMC2 +12V"
#define SDR_FMC2_VADJ_ID "FMC2 VADJ"
#define SDR_FMC2_P3V3_ID "FMC2 +3.3V"
#define SDR_FMC2_VADJ_CURR_ID "FMC2 +12V Curr"
#define SDR_FMC2_12V_CURR_ID "FMC2 VADJ Curr"
#define SDR_FMC2_P3V3_CURR_ID "FMC2 +3.3V Curr"
/* FMC1 12V */
const SDR_type_01h_t SDR_FMC1_12V = {
.hdr.recID_LSB = 0x00, /* Filled by sdr_insert_entry() */
.hdr.recID_MSB = 0x00,
.hdr.SDRversion = 0x51,
.hdr.rectype = TYPE_01,
.hdr.reclength = sizeof(SDR_type_01h_t) - sizeof(SDR_entry_hdr_t),
.ownerID = 0x00, /* i2c address, -> SDR_Init */
.ownerLUN = 0x00, /* sensor owner LUN */
.sensornum = 0x00, /* Filled by sdr_insert_entry() */
/* record body bytes */
.entityID = 0xC1, /* entity id: AMC Module */
.entityinstance = 0x00, /* entity instance -> SDR_Init */
.sensorinit = 0x7f, /* init: event generation + scanning enabled */
.sensorcap = 0x68, /* capabilities: auto re-arm,*/
.sensortype = SENSOR_TYPE_VOLTAGE, /* sensor type: Voltage*/
.event_reading_type = 0x01, /* sensor reading*/
.assertion_event_mask = { 0xFF, /* LSB assert event mask: 3 bit value */
0x0F }, /* MSB assert event mask */
.deassertion_event_mask = { 0xFF, /* LSB deassert event mask: 3 bit value */
0x0F }, /* MSB deassert event mask */
.readable_threshold_mask = 0x3F, /* LSB: readabled Threshold mask: all thresholds are readabled: */
.settable_threshold_mask = 0x3F, /* MSB: setabled Threshold mask: all thresholds are setabled: */
.sensor_units_1 = 0x00, /* sensor units 1 :*/
.sensor_units_2 = 0x04, /* sensor units 2 :*/
.sensor_units_3 = 0x00, /* sensor units 3 :*/
.linearization = 0x00, /* Linearization */
.M = 64, /* M */
.M_tol = 0x00, /* M - Tolerance */
.B = 0x00, /* B */
.B_accuracy = 0x00, /* B - Accuracy */
.acc_exp_sensor_dir = 0x02, /* Sensor direction */
.Rexp_Bexp = 0xD0, /* R-Exp = -3 , B-Exp = 0 */
.analog_flags = 0x03, /* Analogue characteristics flags */
.nominal_reading = 190, /* Nominal reading = 12.285V */
.normal_max = 200, /* Normal maximum */
.normal_min = 0, /* Normal minimum */
.sensor_max_reading = 0xFF, /* Sensor Maximum reading */
.sensor_min_reading = 0x00, /* Sensor Minimum reading */
.upper_nonrecover_thr = 205, /* Upper non-recoverable Threshold */
.upper_critical_thr = 200, /* Upper critical Threshold */
.upper_noncritical_thr = 190, /* Upper non critical Threshold */
.lower_nonrecover_thr = 170, /* Lower non-recoverable Threshold */
.lower_critical_thr = 175, /* Lower critical Threshold */
.lower_noncritical_thr = 180, /* Lower non-critical Threshold */
.pos_thr_hysteresis = 2, /* positive going Threshold hysteresis value */
.neg_thr_hysteresis = 2, /* negative going Threshold hysteresis value */
.reserved1 = 0x00, /* reserved */
.reserved2 = 0x00, /* reserved */
.OEM = 0x00, /* OEM reserved */
.IDtypelen = 0xc0 | STR_SIZE(SDR_FMC1_12V_ID) , /* 8 bit ASCII, number of bytes */
.IDstring = SDR_FMC1_12V_ID /* sensor string */
};
/* FMC1 PVADJ */
const SDR_type_01h_t SDR_FMC1_VADJ = {
.hdr.recID_LSB = 0x00, /* Filled by sdr_insert_entry() */
.hdr.recID_MSB = 0x00,
.hdr.SDRversion = 0x51,
.hdr.rectype = TYPE_01,
.hdr.reclength = sizeof(SDR_type_01h_t) - sizeof(SDR_entry_hdr_t),
.ownerID = 0x00, /* i2c address, -> SDR_Init */
.ownerLUN = 0x00, /* sensor owner LUN */
.sensornum = 0x00, /* Filled by sdr_insert_entry() */
/* record body bytes */
.entityID = 0xC1, /* entity id: AMC Module */
.entityinstance = 0x00, /* entity instance -> SDR_Init */
.sensorinit = 0x7f, /* init: event generation + scanning enabled */
.sensorcap = 0x68, /* capabilities: auto re-arm,*/
.sensortype = SENSOR_TYPE_VOLTAGE, /* sensor type: voltage*/
.event_reading_type = 0x01, /* sensor reading*/
.assertion_event_mask = { 0xFF, /* LSB assert event mask: 3 bit value */
0x0F }, /* MSB assert event mask */
.deassertion_event_mask = { 0xFF, /* LSB deassert event mask: 3 bit value */
0x0F }, /* MSB deassert event mask */
.readable_threshold_mask = 0x3F, /* LSB: readabled Threshold mask: all thresholds are readabled: */
.settable_threshold_mask = 0x3F, /* MSB: setabled Threshold mask: all thresholds are setabled: */
.sensor_units_1 = 0x00, /* sensor units 1 :*/
.sensor_units_2 = 0x04, /* sensor units 2 :*/
.sensor_units_3 = 0x00, /* sensor units 3 :*/
.linearization = 0x00, /* Linearization */
.M = 64, /* M */
.M_tol = 0x00, /* M - Tolerance */
.B = 0x00, /* B */
.B_accuracy = 0x00, /* B - Accuracy */
.acc_exp_sensor_dir = 0x00, /* Sensor direction */
.Rexp_Bexp = 0xD0, /* R-Exp , B-Exp */
.analog_flags = 0x00, /* Analogue characteristics flags */
.nominal_reading = 39, /* Nominal reading */
.normal_max = 47, /* Normal maximum */
.normal_min = 0, /* Normal minimum */
.sensor_max_reading = 0xFF, /* Sensor Maximum reading */
.sensor_min_reading = 0x00, /* Sensor Minimum reading */
.upper_nonrecover_thr = 51, /* Upper non-recoverable Threshold */
.upper_critical_thr = 46, /* Upper critical Threshold */
.upper_noncritical_thr = 43, /* Upper non critical Threshold */
.lower_nonrecover_thr = 28, /* Lower non-recoverable Threshold */
.lower_critical_thr = 32, /* Lower critical Threshold */
.lower_noncritical_thr = 36, /* Lower non-critical Threshold */
.pos_thr_hysteresis = 2, /* positive going Threshold hysteresis value */
.neg_thr_hysteresis = 2, /* negative going Threshold hysteresis value */
.reserved1 = 0x00, /* reserved */
.reserved2 = 0x00, /* reserved */
.OEM = 0x00, /* OEM reserved */
.IDtypelen = 0xc0 | STR_SIZE(SDR_FMC1_VADJ_ID), /* 8 bit ASCII, number of bytes */
.IDstring = SDR_FMC1_VADJ_ID /* sensor string */
};
/* FMC1 P3V3 */
const SDR_type_01h_t SDR_FMC1_P3V3 = {
.hdr.recID_LSB = 0x00, /* Filled by sdr_insert_entry() */
.hdr.recID_MSB = 0x00,
.hdr.SDRversion = 0x51,
.hdr.rectype = TYPE_01,
.hdr.reclength = sizeof(SDR_type_01h_t) - sizeof(SDR_entry_hdr_t),
.ownerID = 0x00, /* i2c address, -> SDR_Init */
.ownerLUN = 0x00, /* sensor owner LUN */
.sensornum = 0x00, /* Filled by sdr_insert_entry() */
/* record body bytes */
.entityID = 0xC1, /* entity id: AMC Module */
.entityinstance = 0x00, /* entity instance -> SDR_Init */
.sensorinit = 0x7f, /* init: event generation + scanning enabled */
.sensorcap = 0x68, /* capabilities: auto re-arm,*/
.sensortype = SENSOR_TYPE_VOLTAGE, /* sensor type: VOLTAGE*/
.event_reading_type = 0x01, /* sensor reading*/
.assertion_event_mask = { 0xFF, /* LSB assert event mask: 3 bit value */
0x0F }, /* MSB assert event mask */
.deassertion_event_mask = { 0xFF, /* LSB deassert event mask: 3 bit value */
0x0F }, /* MSB deassert event mask */
.readable_threshold_mask = 0x3F, /* LSB: readabled Threshold mask: all thresholds are readabled: */
.settable_threshold_mask = 0x3F, /* MSB: setabled Threshold mask: all thresholds are setabled: */
.sensor_units_1 = 0x00, /* sensor units 1 :*/
.sensor_units_2 = 0x04, /* sensor units 2 :*/
.sensor_units_3 = 0x00, /* sensor units 3 :*/
.M = 64, /* M */
.M_tol = 0x00, /* M - Tolerance */
.B = 0x00, /* B */
.B_accuracy = 0x00, /* B - Accuracy */
.acc_exp_sensor_dir = 0x00, /* Sensor direction */
.Rexp_Bexp = 0xD0, /* R-Exp , B-Exp */
.analog_flags = 0x00, /* Analogue characteristics flags */
.nominal_reading = 52, /* Nominal reading */
.normal_max = 59, /* Normal maximum */
.normal_min = 45, /* Normal minimum */
.sensor_max_reading = 0xFF, /* Sensor Maximum reading */
.sensor_min_reading = 0x00, /* Sensor Minimum reading */
.upper_nonrecover_thr = 62, /* Upper non-recoverable Threshold */
.upper_critical_thr = 59, /* Upper critical Threshold */
.upper_noncritical_thr = 55, /* Upper non critical Threshold */
.lower_nonrecover_thr = 42, /* Lower non-recoverable Threshold */
.lower_critical_thr = 45, /* Lower critical Threshold */
.lower_noncritical_thr = 48, /* Lower non-critical Threshold */
.pos_thr_hysteresis = 2, /* positive going Threshold hysteresis value */
.neg_thr_hysteresis = 2, /* negative going Threshold hysteresis value */
.reserved1 = 0x00, /* reserved */
.reserved2 = 0x00, /* reserved */
.OEM = 0x00, /* OEM reserved */
.IDtypelen = 0xc0 | STR_SIZE(SDR_FMC1_P3V3_ID), /* 8 bit ASCII, number of bytes */
.IDstring = SDR_FMC1_P3V3_ID /* sensor string */
};
/* FMC1 12V Current */
const SDR_type_01h_t SDR_FMC1_12V_CURR = {
.hdr.recID_LSB = 0x00, /* Filled by sdr_insert_entry() */
.hdr.recID_MSB = 0x00,
.hdr.SDRversion = 0x51,
.hdr.rectype = TYPE_01,
.hdr.reclength = sizeof(SDR_type_01h_t) - sizeof(SDR_entry_hdr_t),
.ownerID = 0x00, /* i2c address, -> SDR_Init */
.ownerLUN = 0x00, /* sensor owner LUN */
.sensornum = 0x00, /* Filled by sdr_insert_entry() */
/* record body bytes */
.entityID = 0xC1, /* entity id: AMC Module */
.entityinstance = 0x00, /* entity instance -> SDR_Init */
.sensorinit = 0x7f, /* init: event generation + scanning enabled */
.sensorcap = 0x68, /* capabilities: auto re-arm,*/
.sensortype = SENSOR_TYPE_CURRENT, /* sensor type: Voltage*/
.event_reading_type = 0x01, /* sensor reading*/
.assertion_event_mask = { 0xFF, /* LSB assert event mask: 3 bit value */
0x0F }, /* MSB assert event mask */
.deassertion_event_mask = { 0xFF, /* LSB deassert event mask: 3 bit value */
0x0F }, /* MSB deassert event mask */
.readable_threshold_mask = 0x3F, /* LSB: readabled Threshold mask: all thresholds are readabled: */
.settable_threshold_mask = 0x3F, /* MSB: setabled Threshold mask: all thresholds are setabled: */
.sensor_units_1 = 0x80, /* sensor units 1 :*/
.sensor_units_2 = 0x05, /* sensor units 2 :*/
.sensor_units_3 = 0x00, /* sensor units 3 :*/
.linearization = 0x00, /* Linearization */
.M = 32, /* M */
.M_tol = 0x00, /* M - Tolerance */
.B = 0x00, /* B */
.B_accuracy = 0x00, /* B - Accuracy */
.acc_exp_sensor_dir = 0x02, /* Sensor direction */
.Rexp_Bexp = 0xD0, /* R-Exp = -3 , B-Exp = 0 */
.analog_flags = 0x03, /* Analogue characteristics flags */
.nominal_reading = 190, /* Nominal reading = 12.285V */
.normal_max = 156, /* Normal maximum - 5A per sensor */
.normal_min = 0, /* Normal minimum */
.sensor_max_reading = 0xFF, /* Sensor Maximum reading */
.sensor_min_reading = 0x00, /* Sensor Minimum reading */
.upper_nonrecover_thr = 100, /* Upper non-recoverable Threshold */
.upper_critical_thr = 90, /* Upper critical Threshold */
.upper_noncritical_thr = 80, /* Upper non critical Threshold */
.lower_nonrecover_thr = -60, /* Lower non-recoverable Threshold */
.lower_critical_thr = -50, /* Lower critical Threshold */
.lower_noncritical_thr = 10, /* Lower non-critical Threshold */
.pos_thr_hysteresis = 2, /* positive going Threshold hysteresis value */
.neg_thr_hysteresis = 2, /* negative going Threshold hysteresis value */
.reserved1 = 0x00, /* reserved */
.reserved2 = 0x00, /* reserved */
.OEM = 0x00, /* OEM reserved */
.IDtypelen = 0xc0 | STR_SIZE(SDR_FMC1_12V_CURR_ID) , /* 8 bit ASCII, number of bytes */
.IDstring = SDR_FMC1_12V_CURR_ID /* sensor string */
};
/* FMC1 PVADJ Current */
const SDR_type_01h_t SDR_FMC1_VADJ_CURR = {
.hdr.recID_LSB = 0x00, /* Filled by sdr_insert_entry() */
.hdr.recID_MSB = 0x00,
.hdr.SDRversion = 0x51,
.hdr.rectype = TYPE_01,
.hdr.reclength = sizeof(SDR_type_01h_t) - sizeof(SDR_entry_hdr_t),
.ownerID = 0x00, /* i2c address, -> SDR_Init */
.ownerLUN = 0x00, /* sensor owner LUN */
.sensornum = 0x00, /* Filled by sdr_insert_entry() */
/* record body bytes */
.entityID = 0xC1, /* entity id: AMC Module */
.entityinstance = 0x00, /* entity instance -> SDR_Init */
.sensorinit = 0x7f, /* init: event generation + scanning enabled */
.sensorcap = 0x68, /* capabilities: auto re-arm,*/
.sensortype = SENSOR_TYPE_CURRENT, /* sensor type: voltage*/
.event_reading_type = 0x01, /* sensor reading*/
.assertion_event_mask = { 0xFF, /* LSB assert event mask: 3 bit value */
0x0F }, /* MSB assert event mask */
.deassertion_event_mask = { 0xFF, /* LSB deassert event mask: 3 bit value */
0x0F }, /* MSB deassert event mask */
.readable_threshold_mask = 0x3F, /* LSB: readabled Threshold mask: all thresholds are readabled: */
.settable_threshold_mask = 0x3F, /* MSB: setabled Threshold mask: all thresholds are setabled: */
.sensor_units_1 = 0x80, /* sensor units 1 :*/
.sensor_units_2 = 0x05, /* sensor units 2 :*/
.sensor_units_3 = 0x00, /* sensor units 3 :*/
.linearization = 0x00, /* Linearization */
.M = 32, /* M -> Current LSB*20 */
.M_tol = 0x00, /* M - Tolerance */
.B = 0x00, /* B */
.B_accuracy = 0x00, /* B - Accuracy */
.acc_exp_sensor_dir = 0x00, /* Sensor direction */
.Rexp_Bexp = 0xD0, /* R-Exp , B-Exp */
.analog_flags = 0x00, /* Analogue characteristics flags */
.nominal_reading = 39, /* Nominal reading */
.normal_max = 47, /* Normal maximum */
.normal_min = 0, /* Normal minimum */
.sensor_max_reading = 0x7F, /* Sensor Maximum reading */
.sensor_min_reading = 0x80, /* Sensor Minimum reading */
.upper_nonrecover_thr = 100, /* Upper non-recoverable Threshold */
.upper_critical_thr = 90, /* Upper critical Threshold */
.upper_noncritical_thr = 80, /* Upper non critical Threshold */
.lower_nonrecover_thr = -60, /* Lower non-recoverable Threshold */
.lower_critical_thr = -50, /* Lower critical Threshold */
.lower_noncritical_thr = 10, /* Lower non-critical Threshold */
.pos_thr_hysteresis = 2, /* positive going Threshold hysteresis value */
.neg_thr_hysteresis = 2, /* negative going Threshold hysteresis value */
.reserved1 = 0x00, /* reserved */
.reserved2 = 0x00, /* reserved */
.OEM = 0x00, /* OEM reserved */
.IDtypelen = 0xc0 | STR_SIZE(SDR_FMC1_VADJ_CURR_ID), /* 8 bit ASCII, number of bytes */
.IDstring = SDR_FMC1_VADJ_CURR_ID /* sensor string */
};
/* FMC1 P3V3 Current */
const SDR_type_01h_t SDR_FMC1_P3V3_CURR = {
.hdr.recID_LSB = 0x00, /* Filled by sdr_insert_entry() */
.hdr.recID_MSB = 0x00,
.hdr.SDRversion = 0x51,
.hdr.rectype = TYPE_01,
.hdr.reclength = sizeof(SDR_type_01h_t) - sizeof(SDR_entry_hdr_t),
.ownerID = 0x00, /* i2c address, -> SDR_Init */
.ownerLUN = 0x00, /* sensor owner LUN */
.sensornum = 0x00, /* Filled by sdr_insert_entry() */
/* record body bytes */
.entityID = 0xC1, /* entity id: AMC Module */
.entityinstance = 0x00, /* entity instance -> SDR_Init */
.sensorinit = 0x7f, /* init: event generation + scanning enabled */
.sensorcap = 0x68, /* capabilities: auto re-arm,*/
.sensortype = SENSOR_TYPE_CURRENT, /* sensor type: VOLTAGE*/
.event_reading_type = 0x01, /* sensor reading*/
.assertion_event_mask = { 0xFF, /* LSB assert event mask: 3 bit value */
0x0F }, /* MSB assert event mask */
.deassertion_event_mask = { 0xFF, /* LSB deassert event mask: 3 bit value */
0x0F }, /* MSB deassert event mask */
.readable_threshold_mask = 0x3F, /* LSB: readabled Threshold mask: all thresholds are readabled: */
.settable_threshold_mask = 0x3F, /* MSB: setabled Threshold mask: all thresholds are setabled: */
.sensor_units_1 = 0x80, /* sensor units 1 :*/
.sensor_units_2 = 0x05, /* sensor units 2 :*/
.sensor_units_3 = 0x00, /* sensor units 3 :*/
.M = 32, /* M */
.M_tol = 0x00, /* M - Tolerance */
.B = 0x00, /* B */
.B_accuracy = 0x00, /* B - Accuracy */
.acc_exp_sensor_dir = 0x00, /* Sensor direction */
.Rexp_Bexp = 0xD0, /* R-Exp , B-Exp */
.analog_flags = 0x00, /* Analogue characteristics flags */
.nominal_reading = 52, /* Nominal reading */
.normal_max = 59, /* Normal maximum */
.normal_min = 45, /* Normal minimum */
.sensor_max_reading = 0xFF, /* Sensor Maximum reading */
.sensor_min_reading = 0x00, /* Sensor Minimum reading */
.upper_nonrecover_thr = 100, /* Upper non-recoverable Threshold */
.upper_critical_thr = 90, /* Upper critical Threshold */
.upper_noncritical_thr = 80, /* Upper non critical Threshold */
.lower_nonrecover_thr = -60, /* Lower non-recoverable Threshold */
.lower_critical_thr = -50, /* Lower critical Threshold */
.lower_noncritical_thr = 10, /* Lower non-critical Threshold */
.pos_thr_hysteresis = 2, /* positive going Threshold hysteresis value */
.neg_thr_hysteresis = 2, /* negative going Threshold hysteresis value */
.reserved1 = 0x00, /* reserved */
.reserved2 = 0x00, /* reserved */
.OEM = 0x00, /* OEM reserved */
.IDtypelen = 0xc0 | STR_SIZE(SDR_FMC1_P3V3_CURR_ID), /* 8 bit ASCII, number of bytes */
.IDstring = SDR_FMC1_P3V3_CURR_ID /* sensor string */
};
/* FMC2 12V */
const SDR_type_01h_t SDR_FMC2_12V = {
.hdr.recID_LSB = 0x00, /* Filled by sdr_insert_entry() */
.hdr.recID_MSB = 0x00,
.hdr.SDRversion = 0x51,
.hdr.rectype = TYPE_01,
.hdr.reclength = sizeof(SDR_type_01h_t) - sizeof(SDR_entry_hdr_t),
.ownerID = 0x00, /* i2c address, -> SDR_Init */
.ownerLUN = 0x00, /* sensor owner LUN */
.sensornum = 0x00, /* Filled by sdr_insert_entry() */
/* record body bytes */
.entityID = 0xC1, /* entity id: AMC Module */
.entityinstance = 0x00, /* entity instance -> SDR_Init */
.sensorinit = 0x7f, /* init: event generation + scanning enabled */
.sensorcap = 0x68, /* capabilities: auto re-arm,*/
.sensortype = SENSOR_TYPE_VOLTAGE, /* sensor type: Voltage*/
.event_reading_type = 0x01, /* sensor reading*/
.assertion_event_mask = { 0xFF, /* LSB assert event mask: 3 bit value */
0x0F }, /* MSB assert event mask */
.deassertion_event_mask = { 0xFF, /* LSB deassert event mask: 3 bit value */
0x0F }, /* MSB deassert event mask */
.readable_threshold_mask = 0x3F, /* LSB: readabled Threshold mask: all thresholds are readabled: */
.settable_threshold_mask = 0x3F, /* MSB: setabled Threshold mask: all thresholds are setabled: */
.sensor_units_1 = 0x00, /* sensor units 1 :*/
.sensor_units_2 = 0x04, /* sensor units 2 :*/
.sensor_units_3 = 0x00, /* sensor units 3 :*/
.linearization = 0x00, /* Linearization */
.M = 64, /* M */
.M_tol = 0x00, /* M - Tolerance */
.B = 0x00, /* B */
.B_accuracy = 0x00, /* B - Accuracy */
.acc_exp_sensor_dir = 0x02, /* Sensor direction */
.Rexp_Bexp = 0xD0, /* R-Exp = -3 , B-Exp = 0 */
.analog_flags = 0x03, /* Analogue characteristics flags */
.nominal_reading = 190, /* Nominal reading = 12.285V */
.normal_max = 200, /* Normal maximum */
.normal_min = 0, /* Normal minimum */
.sensor_max_reading = 0xFF, /* Sensor Maximum reading */
.sensor_min_reading = 0x00, /* Sensor Minimum reading */
.upper_nonrecover_thr = 205, /* Upper non-recoverable Threshold */
.upper_critical_thr = 200, /* Upper critical Threshold */
.upper_noncritical_thr = 195, /* Upper non critical Threshold */
.lower_nonrecover_thr = 170, /* Lower non-recoverable Threshold */
.lower_critical_thr = 175, /* Lower critical Threshold */
.lower_noncritical_thr = 180, /* Lower non-critical Threshold */
.pos_thr_hysteresis = 2, /* positive going Threshold hysteresis value */
.neg_thr_hysteresis = 2, /* negative going Threshold hysteresis value */
.reserved1 = 0x00, /* reserved */
.reserved2 = 0x00, /* reserved */
.OEM = 0x00, /* OEM reserved */
.IDtypelen = 0xc0 | STR_SIZE(SDR_FMC2_12V_ID), /* 8 bit ASCII, number of bytes */
.IDstring = SDR_FMC2_12V_ID /* sensor string */
};
/* FMC2 PVADJ */
const SDR_type_01h_t SDR_FMC2_VADJ = {
.hdr.recID_LSB = 0x00, /* Filled by sdr_insert_entry() */
.hdr.recID_MSB = 0x00,
.hdr.SDRversion = 0x51,
.hdr.rectype = TYPE_01,
.hdr.reclength = sizeof(SDR_type_01h_t) - sizeof(SDR_entry_hdr_t),
.ownerID = 0x00, /* i2c address, -> SDR_Init */
.ownerLUN = 0x00, /* sensor owner LUN */
.sensornum = 0x00, /* Filled by sdr_insert_entry() */
/* record body bytes */
.entityID = 0xC1, /* entity id: AMC Module */
.entityinstance = 0x00, /* entity instance -> SDR_Init */
.sensorinit = 0x7f, /* init: event generation + scanning enabled */
.sensorcap = 0x68, /* capabilities: auto re-arm,*/
.sensortype = SENSOR_TYPE_VOLTAGE, /* sensor type: voltage*/
.event_reading_type = 0x01, /* sensor reading*/
.assertion_event_mask = { 0xFF, /* LSB assert event mask: 3 bit value */
0x0F }, /* MSB assert event mask */
.deassertion_event_mask = { 0xFF, /* LSB deassert event mask: 3 bit value */
0x0F }, /* MSB deassert event mask */
.readable_threshold_mask = 0x3F, /* LSB: readabled Threshold mask: all thresholds are readabled: */
.settable_threshold_mask = 0x3F, /* MSB: setabled Threshold mask: all thresholds are setabled: */
.sensor_units_1 = 0x00, /* sensor units 1 :*/
.sensor_units_2 = 0x04, /* sensor units 2 :*/
.sensor_units_3 = 0x00, /* sensor units 3 :*/
.linearization = 0x00, /* Linearization */
.M = 64, /* M */
.M_tol = 0x00, /* M - Tolerance */
.B = 0x00, /* B */
.B_accuracy = 0x00, /* B - Accuracy */
.acc_exp_sensor_dir = 0x00, /* Sensor direction */
.Rexp_Bexp = 0xD0, /* R-Exp , B-Exp */
.analog_flags = 0x00, /* Analogue characteristics flags */
.nominal_reading = 39, /* Nominal reading */
.normal_max = 47, /* Normal maximum */
.normal_min = 0, /* Normal minimum */
.sensor_max_reading = 0xFF, /* Sensor Maximum reading */
.sensor_min_reading = 0x00, /* Sensor Minimum reading */
.upper_nonrecover_thr = 51, /* Upper non-recoverable Threshold */
.upper_critical_thr = 46, /* Upper critical Threshold */
.upper_noncritical_thr = 43, /* Upper non critical Threshold */
.lower_nonrecover_thr = 28, /* Lower non-recoverable Threshold */
.lower_critical_thr = 32, /* Lower critical Threshold */
.lower_noncritical_thr = 36, /* Lower non-critical Threshold */
.pos_thr_hysteresis = 2, /* positive going Threshold hysteresis value */
.neg_thr_hysteresis = 2, /* negative going Threshold hysteresis value */
.reserved1 = 0x00, /* reserved */
.reserved2 = 0x00, /* reserved */
.OEM = 0x00, /* OEM reserved */
.IDtypelen = 0xc0 | STR_SIZE(SDR_FMC2_VADJ_ID), /* 8 bit ASCII, number of bytes */
.IDstring = SDR_FMC2_VADJ_ID /* sensor string */
};
/* FMC2 P3V3 */
const SDR_type_01h_t SDR_FMC2_P3V3 = {
.hdr.recID_LSB = 0x00, /* Filled by sdr_insert_entry() */
.hdr.recID_MSB = 0x00,
.hdr.SDRversion = 0x51,
.hdr.rectype = TYPE_01,
.hdr.reclength = sizeof(SDR_type_01h_t) - sizeof(SDR_entry_hdr_t),
.ownerID = 0x00, /* i2c address, -> SDR_Init */
.ownerLUN = 0x00, /* sensor owner LUN */
.sensornum = 0x00, /* Filled by sdr_insert_entry() */
/* record body bytes */
.entityID = 0xC1, /* entity id: AMC Module */
.entityinstance = 0x00, /* entity instance -> SDR_Init */
.sensorinit = 0x7f, /* init: event generation + scanning enabled */
.sensorcap = 0x68, /* capabilities: auto re-arm,*/
.sensortype = SENSOR_TYPE_VOLTAGE, /* sensor type: VOLTAGE*/
.event_reading_type = 0x01, /* sensor reading*/
.assertion_event_mask = { 0xFF, /* LSB assert event mask: 3 bit value */
0x0F }, /* MSB assert event mask */
.deassertion_event_mask = { 0xFF, /* LSB deassert event mask: 3 bit value */
0x0F }, /* MSB deassert event mask */
.readable_threshold_mask = 0x3F, /* LSB: readabled Threshold mask: all thresholds are readabled: */
.settable_threshold_mask = 0x3F, /* MSB: setabled Threshold mask: all thresholds are setabled: */
.sensor_units_1 = 0x00, /* sensor units 1 :*/
.sensor_units_2 = 0x04, /* sensor units 2 :*/
.sensor_units_3 = 0x00, /* sensor units 3 :*/
.linearization = 0x00, /* Linearization */
.M = 64, /* M */
.M_tol = 0x00, /* M - Tolerance */
.B = 0x00, /* B */
.B_accuracy = 0x00, /* B - Accuracy */
.acc_exp_sensor_dir = 0x00, /* Sensor direction */
.Rexp_Bexp = 0xD0, /* R-Exp , B-Exp */
.analog_flags = 0x00, /* Analogue characteristics flags */
.nominal_reading = 52, /* Nominal reading */
.normal_max = 59, /* Normal maximum */
.normal_min = 45, /* Normal minimum */
.sensor_max_reading = 0xFF, /* Sensor Maximum reading */
.sensor_min_reading = 0x00, /* Sensor Minimum reading */
.upper_nonrecover_thr = 62, /* Upper non-recoverable Threshold */
.upper_critical_thr = 59, /* Upper critical Threshold */
.upper_noncritical_thr = 55, /* Upper non critical Threshold */
.lower_nonrecover_thr = 42, /* Lower non-recoverable Threshold */
.lower_critical_thr = 45, /* Lower critical Threshold */
.lower_noncritical_thr = 48, /* Lower non-critical Threshold */
.pos_thr_hysteresis = 2, /* positive going Threshold hysteresis value */
.neg_thr_hysteresis = 2, /* negative going Threshold hysteresis value */
.reserved1 = 0x00, /* reserved */
.reserved2 = 0x00, /* reserved */
.OEM = 0x00, /* OEM reserved */
.IDtypelen = 0xc0 | STR_SIZE(SDR_FMC2_P3V3_ID), /* 8 bit ASCII, number of bytes */
.IDstring = SDR_FMC2_P3V3_ID /* sensor string */
};
/* FMC2 12V Current */
const SDR_type_01h_t SDR_FMC2_12V_CURR = {
.hdr.recID_LSB = 0x00, /* Filled by sdr_insert_entry() */
.hdr.recID_MSB = 0x00,
.hdr.SDRversion = 0x51,
.hdr.rectype = TYPE_01,
.hdr.reclength = sizeof(SDR_type_01h_t) - sizeof(SDR_entry_hdr_t),
.ownerID = 0x00, /* i2c address, -> SDR_Init */
.ownerLUN = 0x00, /* sensor owner LUN */
.sensornum = 0x00, /* Filled by sdr_insert_entry() */
/* record body bytes */
.entityID = 0xC1, /* entity id: AMC Module */
.entityinstance = 0x00, /* entity instance -> SDR_Init */
.sensorinit = 0x7f, /* init: event generation + scanning enabled */
.sensorcap = 0x68, /* capabilities: auto re-arm,*/
.sensortype = SENSOR_TYPE_CURRENT, /* sensor type: Voltage*/
.event_reading_type = 0x01, /* sensor reading*/
.assertion_event_mask = { 0xFF, /* LSB assert event mask: 3 bit value */
0x0F }, /* MSB assert event mask */
.deassertion_event_mask = { 0xFF, /* LSB deassert event mask: 3 bit value */
0x0F }, /* MSB deassert event mask */
.readable_threshold_mask = 0x3F, /* LSB: readabled Threshold mask: all thresholds are readabled: */
.settable_threshold_mask = 0x3F, /* MSB: setabled Threshold mask: all thresholds are setabled: */
.sensor_units_1 = 0x80, /* sensor units 1 :*/
.sensor_units_2 = 0x05, /* sensor units 2 :*/
.sensor_units_3 = 0x00, /* sensor units 3 :*/
.linearization = 0x00, /* Linearization */
.M = 32, /* M */
.M_tol = 0x00, /* M - Tolerance */
.B = 0x00, /* B */
.B_accuracy = 0x00, /* B - Accuracy */
.acc_exp_sensor_dir = 0x02, /* Sensor direction */
.Rexp_Bexp = 0xD0, /* R-Exp = -3 , B-Exp = 0 */
.analog_flags = 0x03, /* Analogue characteristics flags */
.nominal_reading = 190, /* Nominal reading = 12.285V */
.normal_max = 200, /* Normal maximum */
.normal_min = 0, /* Normal minimum */
.sensor_max_reading = 0xFF, /* Sensor Maximum reading */
.sensor_min_reading = 0x00, /* Sensor Minimum reading */
.upper_nonrecover_thr = 100, /* Upper non-recoverable Threshold */
.upper_critical_thr = 90, /* Upper critical Threshold */
.upper_noncritical_thr = 80, /* Upper non critical Threshold */
.lower_nonrecover_thr = -60, /* Lower non-recoverable Threshold */
.lower_critical_thr = -50, /* Lower critical Threshold */
.lower_noncritical_thr = 10, /* Lower non-critical Threshold */
.pos_thr_hysteresis = 2, /* positive going Threshold hysteresis value */
.neg_thr_hysteresis = 2, /* negative going Threshold hysteresis value */
.reserved1 = 0x00, /* reserved */
.reserved2 = 0x00, /* reserved */
.OEM = 0x00, /* OEM reserved */
.IDtypelen = 0xc0 | STR_SIZE(SDR_FMC2_12V_CURR_ID) , /* 8 bit ASCII, number of bytes */
.IDstring = SDR_FMC2_12V_CURR_ID /* sensor string */
};
/* FMC2 PVADJ Current */
const SDR_type_01h_t SDR_FMC2_VADJ_CURR = {
.hdr.recID_LSB = 0x00, /* Filled by sdr_insert_entry() */
.hdr.recID_MSB = 0x00,
.hdr.SDRversion = 0x51,
.hdr.rectype = TYPE_01,
.hdr.reclength = sizeof(SDR_type_01h_t) - sizeof(SDR_entry_hdr_t),
.ownerID = 0x00, /* i2c address, -> SDR_Init */
.ownerLUN = 0x00, /* sensor owner LUN */
.sensornum = 0x00, /* Filled by sdr_insert_entry() */
/* record body bytes */
.entityID = 0xC1, /* entity id: AMC Module */
.entityinstance = 0x00, /* entity instance -> SDR_Init */
.sensorinit = 0x7f, /* init: event generation + scanning enabled */
.sensorcap = 0x68, /* capabilities: auto re-arm,*/
.sensortype = SENSOR_TYPE_CURRENT, /* sensor type: voltage*/
.event_reading_type = 0x01, /* sensor reading*/
.assertion_event_mask = { 0xFF, /* LSB assert event mask: 3 bit value */
0x0F }, /* MSB assert event mask */
.deassertion_event_mask = { 0xFF, /* LSB deassert event mask: 3 bit value */
0x0F }, /* MSB deassert event mask */
.readable_threshold_mask = 0x3F, /* LSB: readabled Threshold mask: all thresholds are readabled: */
.settable_threshold_mask = 0x3F, /* MSB: setabled Threshold mask: all thresholds are setabled: */
.sensor_units_1 = 0x80, /* sensor units 1 :*/
.sensor_units_2 = 0x05, /* sensor units 2 :*/
.sensor_units_3 = 0x00, /* sensor units 3 :*/
.linearization = 0x00, /* Linearization */
.M = 32, /* M */
.M_tol = 0x00, /* M - Tolerance */
.B = 0x00, /* B */
.B_accuracy = 0x00, /* B - Accuracy */
.acc_exp_sensor_dir = 0x00, /* Sensor direction */
.Rexp_Bexp = 0xD0, /* R-Exp , B-Exp */
.analog_flags = 0x00, /* Analogue characteristics flags */
.nominal_reading = 39, /* Nominal reading */
.normal_max = 47, /* Normal maximum */
.normal_min = 0, /* Normal minimum */
.sensor_max_reading = 0xFF, /* Sensor Maximum reading */
.sensor_min_reading = 0x00, /* Sensor Minimum reading */
.upper_nonrecover_thr = 100, /* Upper non-recoverable Threshold */
.upper_critical_thr = 90, /* Upper critical Threshold */
.upper_noncritical_thr = 80, /* Upper non critical Threshold */
.lower_nonrecover_thr = -60, /* Lower non-recoverable Threshold */
.lower_critical_thr = -50, /* Lower critical Threshold */
.lower_noncritical_thr = 10, /* Lower non-critical Threshold */
.pos_thr_hysteresis = 2, /* positive going Threshold hysteresis value */
.neg_thr_hysteresis = 2, /* negative going Threshold hysteresis value */
.reserved1 = 0x00, /* reserved */
.reserved2 = 0x00, /* reserved */
.OEM = 0x00, /* OEM reserved */
.IDtypelen = 0xc0 | STR_SIZE(SDR_FMC2_VADJ_CURR_ID), /* 8 bit ASCII, number of bytes */
.IDstring = SDR_FMC2_VADJ_CURR_ID /* sensor string */
};
/* FMC2 P3V3 Current */
const SDR_type_01h_t SDR_FMC2_P3V3_CURR = {
.hdr.recID_LSB = 0x00, /* Filled by sdr_insert_entry() */
.hdr.recID_MSB = 0x00,
.hdr.SDRversion = 0x51,
.hdr.rectype = TYPE_01,
.hdr.reclength = sizeof(SDR_type_01h_t) - sizeof(SDR_entry_hdr_t),
.ownerID = 0x00, /* i2c address, -> SDR_Init */
.ownerLUN = 0x00, /* sensor owner LUN */
.sensornum = 0x00, /* Filled by sdr_insert_entry() */
/* record body bytes */
.entityID = 0xC1, /* entity id: AMC Module */
.entityinstance = 0x00, /* entity instance -> SDR_Init */
.sensorinit = 0x7f, /* init: event generation + scanning enabled */
.sensorcap = 0x68, /* capabilities: auto re-arm,*/
.sensortype = SENSOR_TYPE_CURRENT, /* sensor type: VOLTAGE*/
.event_reading_type = 0x01, /* sensor reading*/
.assertion_event_mask = { 0xFF, /* LSB assert event mask: 3 bit value */
0x0F }, /* MSB assert event mask */
.deassertion_event_mask = { 0xFF, /* LSB deassert event mask: 3 bit value */
0x0F }, /* MSB deassert event mask */
.readable_threshold_mask = 0x3F, /* LSB: readabled Threshold mask: all thresholds are readabled: */
.settable_threshold_mask = 0x3F, /* MSB: setabled Threshold mask: all thresholds are setabled: */
.sensor_units_1 = 0x80, /* sensor units 1 :*/
.sensor_units_2 = 0x05, /* sensor units 2 :*/
.sensor_units_3 = 0x00, /* sensor units 3 :*/
.M = 32, /* M */
.M_tol = 0x00, /* M - Tolerance */
.B = 0x00, /* B */
.B_accuracy = 0x00, /* B - Accuracy */
.acc_exp_sensor_dir = 0x00, /* Sensor direction */
.Rexp_Bexp = 0xD0, /* R-Exp , B-Exp */
.analog_flags = 0x00, /* Analogue characteristics flags */
.nominal_reading = 52, /* Nominal reading */
.normal_max = 59, /* Normal maximum */
.normal_min = 45, /* Normal minimum */
.sensor_max_reading = 0xFF, /* Sensor Maximum reading */
.sensor_min_reading = 0x00, /* Sensor Minimum reading */
.upper_nonrecover_thr = 100, /* Upper non-recoverable Threshold */
.upper_critical_thr = 90, /* Upper critical Threshold */
.upper_noncritical_thr = 80, /* Upper non critical Threshold */
.lower_nonrecover_thr = -60, /* Lower non-recoverable Threshold */
.lower_critical_thr = -50, /* Lower critical Threshold */
.lower_noncritical_thr = 10, /* Lower non-critical Threshold */
.pos_thr_hysteresis = 2, /* positive going Threshold hysteresis value */
.neg_thr_hysteresis = 2, /* negative going Threshold hysteresis value */
.reserved1 = 0x00, /* reserved */
.reserved2 = 0x00, /* reserved */
.OEM = 0x00, /* OEM reserved */
.IDtypelen = 0xc0 | STR_SIZE(SDR_FMC2_P3V3_CURR_ID), /* 8 bit ASCII, number of bytes */
.IDstring = SDR_FMC2_P3V3_CURR_ID /* sensor string */
};
/* /*
* lm75.c * openMMC -- Open Source modular IPM Controller firmware
* *
* AFCIPMI -- * Copyright (C) 2015-2016 Henrique Silva <henrique.silva@lnls.br>
*
* Copyright (C) 2015
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
...@@ -17,36 +15,40 @@ ...@@ -17,36 +15,40 @@
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* @license GPL-3.0+ <http://spdx.org/licenses/GPL-3.0+>
*/ */
/* FreeRTOS Includes */
#include "FreeRTOS.h" #include "FreeRTOS.h"
#include "task.h" #include "task.h"
#include "port.h" #include "port.h"
/* Project Includes */
#include "sdr.h" #include "sdr.h"
#include "task_priorities.h" #include "task_priorities.h"
#include "board_version.h" #include "board_version.h"
#include "lm75.h" #include "lm75.h"
#include "utils.h"
TaskHandle_t vTaskLM75_Handle; TaskHandle_t vTaskLM75_Handle;
void vTaskLM75( void* Parameters ) void vTaskLM75( void* Parameters )
{ {
TickType_t xLastWakeTime;
/* Task will run every 100ms */
const TickType_t xFrequency = LM75_UPDATE_RATE; const TickType_t xFrequency = LM75_UPDATE_RATE;
uint8_t i2c_bus_id; uint8_t i2c_bus_id;
uint8_t i; uint8_t i;
sensor_data_entry_t * pDATA;
sensor_t * lm75_sensor;
uint8_t temp[2]; uint8_t temp[2];
uint16_t converted_temp; uint16_t converted_temp;
for ( ;; ) { for ( ;; ) {
/* Try to gain the I2C bus */ /* Try to gain the I2C bus */
if (afc_i2c_take_by_busid(I2C_BUS_CPU_ID, &i2c_bus_id, (TickType_t)100) == pdTRUE) { if (i2c_take_by_busid(I2C_BUS_CPU_ID, &i2c_bus_id, (TickType_t)100) == pdTRUE) {
/* Update all temperature sensors readings */ /* Update all temperature sensors readings */
for ( i = 0; i < NUM_SDR; i++ ) { for ( i = 0; i < sdr_count; i++ ) {
/* Check if the handle pointer is not NULL */ /* Check if the handle pointer is not NULL */
if (sensor_array[i].task_handle == NULL) { if (sensor_array[i].task_handle == NULL) {
continue; continue;
...@@ -56,15 +58,15 @@ void vTaskLM75( void* Parameters ) ...@@ -56,15 +58,15 @@ void vTaskLM75( void* Parameters )
continue; continue;
} }
pDATA = sensor_array[i].data; lm75_sensor = &sensor_array[i];
/* Update the temperature reading */ /* Update the temperature reading */
if (xI2CMasterRead( i2c_bus_id, sensor_array[i].slave_addr, &temp[0], 2) == 2) { if (xI2CMasterRead( i2c_bus_id, sensor_array[i].slave_addr, &temp[0], 2) == 2) {
converted_temp = ((temp[0]*10)+((temp[1]>>8)*10)); converted_temp = ((temp[0] << 1) | ((temp[1]>>8)));
pDATA->readout_value = converted_temp; lm75_sensor->readout_value = converted_temp;
} }
} }
afc_i2c_give(i2c_bus_id); i2c_give(i2c_bus_id);
} }
vTaskDelay(xFrequency); vTaskDelay(xFrequency);
} }
...@@ -77,15 +79,248 @@ void LM75_init( void ) ...@@ -77,15 +79,248 @@ void LM75_init( void )
uint8_t i, j; uint8_t i, j;
for ( j = 0, i = 0; i < NUM_SDR && j < LM75_MAX_COUNT; i++, j++ ) { for ( j = 0, i = 0; i < NUM_SDR && j < LM75_MAX_COUNT; i++, j++ ) {
if (afc_i2c_take_by_busid(I2C_BUS_CPU_ID, &i2c_bus_id, (TickType_t) 50) == pdFALSE) { if (i2c_take_by_busid(I2C_BUS_CPU_ID, &i2c_bus_id, (TickType_t) 50) == pdFALSE) {
continue; continue;
} }
uint8_t cmd[3] = {0x00, 0x01, 0x9F}; uint8_t cmd[3] = {0x00, 0x01, 0x9F};
xI2CMasterWrite(i2c_id, sensor_array[i].slave_addr, ch, 3); xI2CMasterWrite(i2c_id, sensor_array[i].slave_addr, ch, 3);
afc_i2c_give( i2c_bus_id ); i2c_give( i2c_bus_id );
} }
#endif #endif
/* Why does this Task's stack is so large? About 320 bytes */
xTaskCreate( vTaskLM75, "LM75", 330, (void *) NULL, tskLM75SENSOR_PRIORITY, &vTaskLM75_Handle); xTaskCreate( vTaskLM75, "LM75", 330, (void *) NULL, tskLM75SENSOR_PRIORITY, &vTaskLM75_Handle);
/* Include all sensors on SDR */
sdr_insert_entry( TYPE_01, (void *) &SDR_LM75_uC, &vTaskLM75_Handle, 0, 0x4C );
sdr_insert_entry( TYPE_01, (void *) &SDR_LM75_CLOCK_SWITCH, &vTaskLM75_Handle, 0, 0x4D );
sdr_insert_entry( TYPE_01, (void *) &SDR_LM75_DCDC, &vTaskLM75_Handle, 0, 0x4E );
sdr_insert_entry( TYPE_01, (void *) &SDR_LM75_RAM, &vTaskLM75_Handle, 0, 0x4F );
} }
/* LM75 SDR List */
const SDR_type_01h_t SDR_LM75_uC = {
.hdr.recID_LSB = 0x00, /* Filled by sdr_insert_entry() */
.hdr.recID_MSB = 0x00,
.hdr.SDRversion = 0x51,
.hdr.rectype = TYPE_01,
.hdr.reclength = sizeof(SDR_type_01h_t) - sizeof(SDR_entry_hdr_t),
.ownerID = 0x00, /* i2c address, -> SDR_Init */
.ownerLUN = 0x00, /* sensor owner LUN */
.sensornum = 0x00, /* Filled by sdr_insert_entry() */
/* record body bytes */
.entityID = 0xC1, /* entity id: AMC Module */
.entityinstance = 0x00, /* entity instance -> SDR_Init */
.sensorinit = 0x7f, /* init: event generation + scanning enabled */
.sensorcap = 0x68, /* capabilities: auto re-arm,*/
.sensortype = SENSOR_TYPE_TEMPERATURE, /* sensor type */
.event_reading_type = 0x01, /* sensor reading*/
.assertion_event_mask = { 0xFF, /* LSB assert event mask: 3 bit value */
0x0F }, /* MSB assert event mask */
.deassertion_event_mask = { 0xFF, /* LSB deassert event mask: 3 bit value */
0x0F }, /* MSB deassert event mask */
.readable_threshold_mask = 0x3F, /* LSB: readabled Threshold mask: all thresholds are readabled: */
.settable_threshold_mask = 0x3F, /* MSB: setabled Threshold mask: all thresholds are setabled: */
.sensor_units_1 = 0x00, /* sensor units 1 :*/
.sensor_units_2 = 0x01, /* sensor units 2 :*/
.sensor_units_3 = 0x00, /* sensor units 3 :*/
.linearization = 0x00, /* Linearization */
.M = 5, /* M */
.M_tol = 0x00, /* M - Tolerance */
.B = 0x00, /* B */
.B_accuracy = 0x00, /* B - Accuracy */
.acc_exp_sensor_dir = 0x00, /* Sensor direction */
.Rexp_Bexp = 0xF0, /* R-Exp , B-Exp */
.analog_flags = 0x03, /* Analogue characteristics flags */
.nominal_reading = (30 << 1), /* Nominal reading */
.normal_max = (50 << 1), /* Normal maximum */
.normal_min = (20 << 1), /* Normal minimum */
.sensor_max_reading = 0xFF, /* Sensor Maximum reading */
.sensor_min_reading = 0x00, /* Sensor Minimum reading */
.upper_nonrecover_thr = (75 << 1), /* Upper non-recoverable Threshold */
.upper_critical_thr = (65 << 1), /* Upper critical Threshold */
.upper_noncritical_thr = (55 << 1), /* Upper non critical Threshold */
.lower_nonrecover_thr = (5 << 1), /* Lower non-recoverable Threshold */
.lower_critical_thr = (10 << 1), /* Lower critical Threshold */
.lower_noncritical_thr = (20 << 1), /* Lower non-critical Threshold */
.pos_thr_hysteresis = 2, /* positive going Threshold hysteresis value */
.neg_thr_hysteresis = 2, /* negative going Threshold hysteresis value */
.reserved1 = 0x00, /* reserved */
.reserved2 = 0x00, /* reserved */
.OEM = 0x00, /* OEM reserved */
.IDtypelen = 0xc0 | STR_SIZE("TEMP UC"), /* 8 bit ASCII, number of bytes */
.IDstring = "TEMP UC" /* sensor string */
};
const SDR_type_01h_t SDR_LM75_CLOCK_SWITCH = {
.hdr.recID_LSB = 0x00, /* Filled by sdr_insert_entry() */
.hdr.recID_MSB = 0x00,
.hdr.SDRversion = 0x51,
.hdr.rectype = TYPE_01,
.hdr.reclength = sizeof(SDR_type_01h_t) - sizeof(SDR_entry_hdr_t),
.ownerID = 0x00, /* i2c address, -> SDR_Init */
.ownerLUN = 0x00, /* sensor owner LUN */
.sensornum = 0x00, /* Filled by sdr_insert_entry() */
/* record body bytes */
.entityID = 0xC1, /* entity id: AMC Module */
.entityinstance = 0x00, /* entity instance -> SDR_Init */
.sensorinit = 0x7f, /* init: event generation + scanning enabled */
.sensorcap = 0x68, /* capabilities: auto re-arm,*/
.sensortype = SENSOR_TYPE_TEMPERATURE, /* sensor type */
.event_reading_type = 0x01, /* sensor reading*/
.assertion_event_mask = { 0xFF, /* LSB assert event mask: 3 bit value */
0x0F }, /* MSB assert event mask */
.deassertion_event_mask = { 0xFF, /* LSB deassert event mask: 3 bit value */
0x0F }, /* MSB deassert event mask */
.readable_threshold_mask = 0x3F, /* LSB: readabled Threshold mask: all thresholds are readabled: */
.settable_threshold_mask = 0x3F, /* MSB: setabled Threshold mask: all thresholds are setabled: */
.sensor_units_1 = 0x00, /* sensor units 1 :*/
.sensor_units_2 = 0x01, /* sensor units 2 :*/
.sensor_units_3 = 0x00, /* sensor units 3 :*/
.linearization = 0x00, /* Linearization */
.M = 5, /* M */
.M_tol = 0x00, /* M - Tolerance */
.B = 0x00, /* B */
.B_accuracy = 0x00, /* B - Accuracy */
.acc_exp_sensor_dir = 0x00, /* Sensor direction */
.Rexp_Bexp = 0xF0, /* R-Exp , B-Exp */
.analog_flags = 0x03, /* Analogue characteristics flags */
.nominal_reading = (30 << 1), /* Nominal reading */
.normal_max = (50 << 1), /* Normal maximum */
.normal_min = (20 << 1), /* Normal minimum */
.sensor_max_reading = 0xFF, /* Sensor Maximum reading */
.sensor_min_reading = 0x00, /* Sensor Minimum reading */
.upper_nonrecover_thr = (75 << 1), /* Upper non-recoverable Threshold */
.upper_critical_thr = (65 << 1), /* Upper critical Threshold */
.upper_noncritical_thr = (55 << 1), /* Upper non critical Threshold */
.lower_nonrecover_thr = (5 << 1), /* Lower non-recoverable Threshold */
.lower_critical_thr = (10 << 1), /* Lower critical Threshold */
.lower_noncritical_thr = (20 << 1), /* Lower non-critical Threshold */
.pos_thr_hysteresis = 2, /* positive going Threshold hysteresis value */
.neg_thr_hysteresis = 2, /* negative going Threshold hysteresis value */
.reserved1 = 0x00, /* reserved */
.reserved2 = 0x00, /* reserved */
.OEM = 0x00, /* OEM reserved */
.IDtypelen = 0xc0 | STR_SIZE("TEMP CLK SWITCH"), /* 8 bit ASCII, number of bytes */
.IDstring = "TEMP CLK SWITCH" /* sensor string */
};
const SDR_type_01h_t SDR_LM75_DCDC = {
.hdr.recID_LSB = 0x00, /* Filled by sdr_insert_entry() */
.hdr.recID_MSB = 0x00,
.hdr.SDRversion = 0x51,
.hdr.rectype = TYPE_01,
.hdr.reclength = sizeof(SDR_type_01h_t) - sizeof(SDR_entry_hdr_t),
.ownerID = 0x00, /* i2c address, -> SDR_Init */
.ownerLUN = 0x00, /* sensor owner LUN */
.sensornum = 0x00, /* Filled by sdr_insert_entry() */
/* record body bytes */
.entityID = 0xC1, /* entity id: AMC Module */
.entityinstance = 0x00, /* entity instance -> SDR_Init */
.sensorinit = 0x7f, /* init: event generation + scanning enabled */
.sensorcap = 0x68, /* capabilities: auto re-arm,*/
.sensortype = SENSOR_TYPE_TEMPERATURE, /* sensor type */
.event_reading_type = 0x01, /* sensor reading*/
.assertion_event_mask = { 0xFF, /* LSB assert event mask: 3 bit value */
0x0F }, /* MSB assert event mask */
.deassertion_event_mask = { 0xFF, /* LSB deassert event mask: 3 bit value */
0x0F }, /* MSB deassert event mask */
.readable_threshold_mask = 0x3F, /* LSB: readabled Threshold mask: all thresholds are readabled: */
.settable_threshold_mask = 0x3F, /* MSB: setabled Threshold mask: all thresholds are setabled: */
.sensor_units_1 = 0x00, /* sensor units 1 :*/
.sensor_units_2 = 0x01, /* sensor units 2 :*/
.sensor_units_3 = 0x00, /* sensor units 3 :*/
.linearization = 0x00, /* Linearization */
.M = 5, /* M */
.M_tol = 0x00, /* M - Tolerance */
.B = 0x00, /* B */
.B_accuracy = 0x00, /* B - Accuracy */
.acc_exp_sensor_dir = 0x00, /* Sensor direction */
.Rexp_Bexp = 0xF0, /* R-Exp , B-Exp */
.analog_flags = 0x03, /* Analogue characteristics flags */
.nominal_reading = (30 << 1), /* Nominal reading */
.normal_max = (50 << 1), /* Normal maximum */
.normal_min = (20 << 1), /* Normal minimum */
.sensor_max_reading = 0xFF, /* Sensor Maximum reading */
.sensor_min_reading = 0x00, /* Sensor Minimum reading */
.upper_nonrecover_thr = (75 << 1), /* Upper non-recoverable Threshold */
.upper_critical_thr = (65 << 1), /* Upper critical Threshold */
.upper_noncritical_thr = (55 << 1), /* Upper non critical Threshold */
.lower_nonrecover_thr = (5 << 1), /* Lower non-recoverable Threshold */
.lower_critical_thr = (10 << 1), /* Lower critical Threshold */
.lower_noncritical_thr = (20 << 1), /* Lower non-critical Threshold */
.pos_thr_hysteresis = 2, /* positive going Threshold hysteresis value */
.neg_thr_hysteresis = 2, /* negative going Threshold hysteresis value */
.reserved1 = 0x00, /* reserved */
.reserved2 = 0x00, /* reserved */
.OEM = 0x00, /* OEM reserved */
.IDtypelen = 0xc0 | STR_SIZE("TEMP DCDC"), /* 8 bit ASCII, number of bytes */
.IDstring = "TEMP DCDC" /* sensor string */
};
const SDR_type_01h_t SDR_LM75_RAM = {
.hdr.recID_LSB = 0x00, /* Filled by sdr_insert_entry() */
.hdr.recID_MSB = 0x00,
.hdr.SDRversion = 0x51,
.hdr.rectype = TYPE_01,
.hdr.reclength = sizeof(SDR_type_01h_t) - sizeof(SDR_entry_hdr_t),
.ownerID = 0x00, /* i2c address, -> SDR_Init */
.ownerLUN = 0x00, /* sensor owner LUN */
.sensornum = 0x00, /* Filled by sdr_insert_entry() */
/* record body bytes */
.entityID = 0xC1, /* entity id: AMC Module */
.entityinstance = 0x00, /* entity instance -> SDR_Init */
.sensorinit = 0x7f, /* init: event generation + scanning enabled */
.sensorcap = 0x68, /* capabilities: auto re-arm,*/
.sensortype = SENSOR_TYPE_TEMPERATURE, /* sensor type */
.event_reading_type = 0x01, /* sensor reading*/
.assertion_event_mask = { 0xFF, /* LSB assert event mask: 3 bit value */
0x0F }, /* MSB assert event mask */
.deassertion_event_mask = { 0xFF, /* LSB deassert event mask: 3 bit value */
0x0F }, /* MSB deassert event mask */
.readable_threshold_mask = 0x3F, /* LSB: readabled Threshold mask: all thresholds are readabled: */
.settable_threshold_mask = 0x3F, /* MSB: setabled Threshold mask: all thresholds are setabled: */
.sensor_units_1 = 0x00, /* sensor units 1 :*/
.sensor_units_2 = 0x01, /* sensor units 2 :*/
.sensor_units_3 = 0x00, /* sensor units 3 :*/
.linearization = 0x00, /* Linearization */
.M = 5, /* M */
.M_tol = 0x00, /* M - Tolerance */
.B = 0x00, /* B */
.B_accuracy = 0x00, /* B - Accuracy */
.acc_exp_sensor_dir = 0x00, /* Sensor direction */
.Rexp_Bexp = 0xF0, /* R-Exp , B-Exp */
.analog_flags = 0x03, /* Analogue characteristics flags */
.nominal_reading = (30 << 1), /* Nominal reading */
.normal_max = (50 << 1), /* Normal maximum */
.normal_min = (20 << 1), /* Normal minimum */
.sensor_max_reading = 0xFF, /* Sensor Maximum reading */
.sensor_min_reading = 0x00, /* Sensor Minimum reading */
.upper_nonrecover_thr = (75 << 1), /* Upper non-recoverable Threshold */
.upper_critical_thr = (65 << 1), /* Upper critical Threshold */
.upper_noncritical_thr = (55 << 1), /* Upper non critical Threshold */
.lower_nonrecover_thr = (5 << 1), /* Lower non-recoverable Threshold */
.lower_critical_thr = (10 << 1), /* Lower critical Threshold */
.lower_noncritical_thr = (20 << 1), /* Lower non-critical Threshold */
.pos_thr_hysteresis = 2, /* positive going Threshold hysteresis value */
.neg_thr_hysteresis = 2, /* negative going Threshold hysteresis value */
.reserved1 = 0x00, /* reserved */
.reserved2 = 0x00, /* reserved */
.OEM = 0x00, /* OEM reserved */
.IDtypelen = 0xc0 | STR_SIZE("TEMP RAM"), /* 8 bit ASCII, number of bytes */
.IDstring = "TEMP RAM" /* sensor string */
};
/* /*
* AFCIPMI -- * openMMC -- Open Source modular IPM Controller firmware
* *
* Copyright (C) 2015 Henrique Silva <henrique.silva@lnls.br> * Copyright (C) 2015-2016 Henrique Silva <henrique.silva@lnls.br>
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
...@@ -15,6 +15,8 @@ ...@@ -15,6 +15,8 @@
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* @license GPL-3.0+ <http://spdx.org/licenses/GPL-3.0+>
*/ */
/*! /*!
...@@ -29,10 +31,15 @@ ...@@ -29,10 +31,15 @@
#define LM75_H_ #define LM75_H_
#define LM75_MAX_COUNT 4 #define LM75_MAX_COUNT 4
#define LM75_UPDATE_RATE 100 #define LM75_UPDATE_RATE 500
extern TaskHandle_t vTaskLM75_Handle; extern TaskHandle_t vTaskLM75_Handle;
const SDR_type_01h_t SDR_LM75_uC;
const SDR_type_01h_t SDR_LM75_CLOCK_SWITCH;
const SDR_type_01h_t SDR_LM75_DCDC;
const SDR_type_01h_t SDR_LM75_RAM;
void LM75_init( void ); void LM75_init( void );
void vTaskLM75( void* Parameters ); void vTaskLM75( void* Parameters );
......
/*
* openMMC -- Open Source modular IPM Controller firmware
*
* Copyright (C) 2015-2016 Henrique Silva <henrique.silva@lnls.br>
*
* 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 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* @license GPL-3.0+ <http://spdx.org/licenses/GPL-3.0+>
*/
#ifndef SENSORS_H_ #ifndef SENSORS_H_
#define SENSORS_H_ #define SENSORS_H_
......
/*
* openMMC -- Open Source modular IPM Controller firmware
*
* Copyright (C) 2015-2016 Henrique Silva <henrique.silva@lnls.br>
*
* 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 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* @license GPL-3.0+ <http://spdx.org/licenses/GPL-3.0+>
*/
#ifndef TASK_PRIORITIES_H_ #ifndef TASK_PRIORITIES_H_
#define TASK_PRIORITIES_H_ #define TASK_PRIORITIES_H_
...@@ -5,22 +26,21 @@ ...@@ -5,22 +26,21 @@
#define tskIDLE_PRIORITY 0 #define tskIDLE_PRIORITY 0
#endif #endif
#define tskLED_PRIORITY (tskIDLE_PRIORITY+1) #define tskLED_PRIORITY (tskIDLE_PRIORITY+1)
#define tskFPGA_COMM_PRIORITY (tskIDLE_PRIORITY+1) #define tskFPGA_COMM_PRIORITY (tskIDLE_PRIORITY+1)
#define tskWATCHDOG_PRIORITY (tskIDLE_PRIORITY+1)
#define tskSENSOR_PRIORITY (tskIDLE_PRIORITY+2) #define tskSENSOR_PRIORITY (tskIDLE_PRIORITY+2)
#define tskHOTSWAP_PRIORITY (tskIDLE_PRIORITY+2)
#define tskLM75SENSOR_PRIORITY (tskIDLE_PRIORITY+2)
#define tskHOTSWAP_PRIORITY (tskIDLE_PRIORITY+2) #define tskINA220SENSOR_PRIORITY (tskIDLE_PRIORITY+2)
#define tskLM75SENSOR_PRIORITY (tskIDLE_PRIORITY+2)
#define tskINA220SENSOR_PRIORITY (tskIDLE_PRIORITY+2)
#define tskPAYLOAD_PRIORITY (tskIDLE_PRIORITY+3) #define tskPAYLOAD_PRIORITY (tskIDLE_PRIORITY+3)
#define tskIPMI_HANDLERS_PRIORITY (tskIDLE_PRIORITY+4) #define tskIPMI_HANDLERS_PRIORITY (tskIDLE_PRIORITY+4)
#define tskIPMI_PRIORITY (tskIDLE_PRIORITY+4) #define tskIPMI_PRIORITY (tskIDLE_PRIORITY+4)
#define tskIPMB_RX_PRIORITY (tskIDLE_PRIORITY+5) #define tskIPMB_RX_PRIORITY (tskIDLE_PRIORITY+5)
#define tskIPMB_TX_PRIORITY (tskIDLE_PRIORITY+5) #define tskIPMB_TX_PRIORITY (tskIDLE_PRIORITY+5)
#endif #endif
/*
* openMMC -- Open Source modular IPM Controller firmware
*
* Copyright (C) 2015-2016 Henrique Silva <henrique.silva@lnls.br>
*
* 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 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* @license GPL-3.0+ <http://spdx.org/licenses/GPL-3.0+>
*/
/*! @file utils.c
@brief General utilities functions
@author Henrique Silva
*/
/* Kernel includes. */
#include "FreeRTOS.h"
#include "utils.h"
/*! @brief Calculate the difference between 2 tick values
* Since he tick counter can overflow, we need to check if the current value is higher than the start time before performing any calculations.
* The Tick counter is expected to overflow at the portMAX_DELAY value
* @param current_time Current tick count
* @param start_time Start tick count
*
* @return Tick difference between arguments
*/
TickType_t getTickDifference(TickType_t current_time, TickType_t start_time)
{
TickType_t result = 0;
if (current_time < start_time) {
result = start_time - current_time;
result = portMAX_DELAY - result;
} else {
result = current_time - start_time;
}
return result;
}
/* Include chksum calculation function */
/*! @brief Calculate a n-byte message 2's complement checksum.
* The checksum byte is calculated by perfoming a simple 8bit 2's complement of the sum of all previous bytes.
* Since we're using a unsigned int to hold the checksum value, we only need to subtract all bytes from it.
* @param buffer Pointer to the message bytes.
* @param range How many bytes will be used in the calculation.
*
* @return Checksum of the specified bytes of the buffer.
*/
uint8_t calculate_chksum ( uint8_t * buffer, uint8_t range )
{
configASSERT( buffer != NULL );
uint8_t chksum = 0;
uint8_t i;
for ( i = 0; i < range; i++ ) {
chksum -= buffer[i];
}
return chksum;
}
/* Compare two buffers' size and data
* Returns 0 if equal, 0xFF if different */
uint8_t cmpBuffs( uint32_t *bufa, uint32_t len_a, uint32_t *bufb, uint32_t len_b )
{
uint16_t i;
if (len_a != len_b) {
return 0xFF;
}
for( i = 0; i<len_a; i++ ) {
if( *bufa != *bufb ) {
return (0xFF);
}
bufa++;
bufb++;
}
return (0);
}
uint8_t isPowerOfTwo( uint8_t x )
{
return ((x != 0) && !(x & (x - 1)));
}
/*
* openMMC -- Open Source modular IPM Controller firmware
*
* Copyright (C) 2015-2016 Henrique Silva <henrique.silva@lnls.br>
*
* 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 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* @license GPL-3.0+ <http://spdx.org/licenses/GPL-3.0+>
*/
/*! @file utils.h
@brief General utilities functions
@author Henrique Silva
*/
#define STR(x) _STR(x)
#define _STR(x) #x
#define STR_SIZE(x) (sizeof(x) -1)
TickType_t getTickDifference( TickType_t current_time, TickType_t start_time );
uint8_t calculate_chksum( uint8_t * buffer, uint8_t range );
uint8_t cmpBuffs( uint32_t *buf_a, uint32_t len_a, uint32_t *bufb, uint32_t len_b );
uint8_t isPowerOfTwo( uint8_t x );
/*
* openMMC -- Open Source modular IPM Controller firmware
*
* Copyright (C) 2015-2016 Henrique Silva <henrique.silva@lnls.br>
*
* 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 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* @license GPL-3.0+ <http://spdx.org/licenses/GPL-3.0+>
*/
/*!
* @file watchdog.c
* @author Henrique Silva <henrique.silva@lnls.br>, LNLS
* @date December 2015
*
* @brief Reset the uC if it fails to reload the watchdog timer
*/
/* FreeRTOS includes */
#include "FreeRTOS.h"
#include "task.h"
#include "semphr.h"
/* Project includes */
#include "port.h"
#include "watchdog.h"
#include "task_priorities.h"
#define WATCHDOG_CLK_FREQ 8000000
#define WATCHDOG_TIMEOUT 1000 /* in milisseconds */
#define WATCHDOG_FEED_DELAY (WATCHDOG_TIMEOUT/3)*2
SemaphoreHandle_t watchdog_smphr;
void watchdog_init( void )
{
wdt_init();
wdt_config();
wdt_set_timeout(((WATCHDOG_TIMEOUT/1000)*WATCHDOG_CLK_FREQ));
watchdog_smphr = xSemaphoreCreateBinary();
xTaskCreate( WatchdogTask, (const char *) "Watchdog Task", configMINIMAL_STACK_SIZE, (void * ) NULL, tskWATCHDOG_PRIORITY, ( TaskHandle_t * ) NULL);
}
void WatchdogTask (void * Parameters)
{
wdt_start();
for ( ;; ) {
if (xSemaphoreTake(watchdog_smphr, 0)) {
NVIC_SystemReset();
}
wdt_feed();
vTaskDelay(WATCHDOG_FEED_DELAY);
}
}
void watchdog_reset_mcu( void )
{
xSemaphoreGive(watchdog_smphr);
}
/*
* openMMC -- Open Source modular IPM Controller firmware
*
* Copyright (C) 2015-2016 Henrique Silva <henrique.silva@lnls.br>
*
* 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 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* @license GPL-3.0+ <http://spdx.org/licenses/GPL-3.0+>
*/
#ifndef WATCHDOG_H_
#define WATCHDOG_H_
void watchdog_init( void );
void WatchdogTask( void * Parameters );
void watchdog_reset_mcu( void );
#endif
##Include selected board files
message(STATUS "Selected Board: ${BOARD}")
if(NOT BOARD)
message(FATAL_ERROR "${BoldRed}Target board was not selected!${ColourReset}")
endif()
#BUG: Regexp will match AFC and AFCK
if(${BOARD} MATCHES "^(AFC)")
add_subdirectory(afc)
else()
message(FATAL_ERROR "${BoldRed}Selected board \"${BOARD}\" is not implemented!${ColourReset}")
endif()
#Normalize strings to upper case
string(TOUPPER "${TARGET_CONTROLLER}" TARGET_CONTROLLER_UPPER)
set(TARGET_CONTROLLER "${TARGET_CONTROLLER_UPPER}" CACHE STRING "Target Controller")
string(TOUPPER "${TARGET_BOARD_NAME}" TARGET_BOARD_UPPER)
set(TARGET_BOARD_NAME "${TARGET_BOARD_UPPER}" CACHE STRING "Target Board Name")
#Set the modified variables in the main scope
set(PROJ_SRCS ${PROJ_SRCS} PARENT_SCOPE)
set(PROJ_HDRS ${PROJ_HDRS} PARENT_SCOPE)
set(TARGET_MODULES ${TARGET_MODULES} PARENT_SCOPE)
set(MODULES_FLAGS ${MODULES_FLAGS} PARENT_SCOPE)
#Select which microcontroller and board are being used
set(TARGET_CONTROLLER "LPC1764" CACHE STRING "Target MMC Controller")
set(TARGET_BOARD_NAME "AFC3_1" CACHE STRING "Board Name")
set(TARGET_BOARD_MAJOR 3 CACHE STRING "Board Major Version")
set(TARGET_BOARD_MINOR 1 CACHE STRING "Board Minor Version")
#List all modules used by this board
set(TARGET_MODULES
"FRU"
"PAYLOAD"
"SDR"
"WATCHDOG"
"JTAG_SWITCH"
"CLOCK_SWITCH"
"FPGA_SPI"
"DAC_AD84XX"
"HOTSWAP_SENSOR"
"TEMPERATURE_SENSOR"
"VOLTAGE_SENSOR"
"HPM"
)
set(BOARD_PATH ${CMAKE_CURRENT_SOURCE_DIR})
#Include the modules sources
if (";${TARGET_MODULES};" MATCHES ";JTAG_SWITCH;")
set(PROJ_SRCS ${PROJ_SRCS} ${BOARD_PATH}/jtag.c )
set(MODULES_FLAGS "${MODULES_FLAGS} -DMODULE_JTAG_SWITCH")
endif()
if (";${TARGET_MODULES};" MATCHES ";CLOCK_SWITCH;")
set(PROJ_SRCS ${PROJ_SRCS} ${BOARD_PATH}/adn4604.c )
set(MODULES_FLAGS "${MODULES_FLAGS} -DMODULE_CLOCK_SWITCH")
endif()
if (";${TARGET_MODULES};" MATCHES ";FPGA_SPI;")
set(PROJ_SRCS ${PROJ_SRCS} ${BOARD_PATH}/fpga_spi.c )
set(MODULES_FLAGS "${MODULES_FLAGS} -DMODULE_FPGA_SPI")
endif()
if (";${TARGET_MODULES};" MATCHES ";DAC_AD84XX;")
set(PROJ_SRCS ${PROJ_SRCS} ${BOARD_PATH}/ad84xx.c )
set(MODULES_FLAGS "${MODULES_FLAGS} -DMODULE_DAC_AD84XX")
endif()
#Extra definitions
if (WRITE_ID_EEPROM)
message(STATUS "EEPROM ID writing enabled!")
add_definitions(-DWRITE_ID_EEPROM)
set(WRITE_ID_EEPROM false CACHE BOOL "Set this flag to enable writing the board ID on the EEPROM" FORCE)
endif()
#Set the variables in the main scope
set(TARGET_MODULES ${TARGET_MODULES} PARENT_SCOPE)
set(MODULES_FLAGS ${MODULES_FLAGS} PARENT_SCOPE)
set(PROJ_SRCS ${PROJ_SRCS} PARENT_SCOPE)
set(PROJ_HDRS ${PROJ_HDRS} ${BOARD_PATH})
set(PROJ_HDRS ${PROJ_HDRS} PARENT_SCOPE)
/*
* openMMC -- Open Source modular IPM Controller firmware
*
* Copyright (C) 2015 Henrique Silva <henrique.silva@lnls.br>
*
* 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 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* @license GPL-3.0+ <http://spdx.org/licenses/GPL-3.0+>
*/
/* Project Includes */
#include "port.h"
#include "pin_mapping.h"
#include "ad84xx.h"
#define DAC_VADJ_SPI_BITRATE 10000000
#define DAC_VADJ_FRAME_SIZE 10
void dac_vadj_init( void )
{
gpio_set_pin_dir( GPIO_DAC_VADJ_RST_PORT, GPIO_DAC_VADJ_RST_PIN, OUTPUT);
/* Reset the AD84xx while initializing the SSP interface */
gpio_set_pin_state( GPIO_DAC_VADJ_RST_PORT, GPIO_DAC_VADJ_RST_PIN, LOW);
spi_config( DAC_VADJ_SPI_BITRATE, DAC_VADJ_FRAME_SIZE, SPI_MASTER, SPI_POLLING );
gpio_set_pin_state( GPIO_DAC_VADJ_RST_PORT, GPIO_DAC_VADJ_RST_PIN, HIGH);
}
void dac_vadj_config( uint8_t addr, uint8_t val )
{
uint16_t data = (addr << 8) | (val);
spi_assertSSEL();
spi_write( (uint8_t *) &data, sizeof(data) );
spi_deassertSSEL();
}
/*
* openMMC -- Open Source modular IPM Controller firmware
*
* Copyright (C) 2015 Henrique Silva <henrique.silva@lnls.br>
*
* 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 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* @license GPL-3.0+ <http://spdx.org/licenses/GPL-3.0+>
*/
#ifndef AD84XX_H_
#define AD84XX_H_
void dac_vadj_init( void );
void dac_vadj_config( uint8_t addr, uint8_t val );
#endif
/* /*
* adn4604.c * openMMC -- Open Source modular IPM Controller firmware
* *
* AFCIPMI -- * Copyright (C) 2015 Henrique Silva <henrique.silva@lnls.br>
*
* Copyright (C) 2015
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
...@@ -17,31 +15,45 @@ ...@@ -17,31 +15,45 @@
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* @license GPL-3.0+ <http://spdx.org/licenses/GPL-3.0+>
*/ */
/* FreeRTOS Includes */
#include "FreeRTOS.h" #include "FreeRTOS.h"
/* Project Includes */
#include "adn4604.h" #include "adn4604.h"
#include "pin_mapping.h" #include "pin_mapping.h"
#include "board_version.h" #include "board_version.h"
void adn4604_setup(void) { void adn4604_setup(void)
uint8_t i2c_bus_id = I2C1; {
uint8_t i2c_bus_id;
uint8_t adn_slave_addr = 0x4B; uint8_t adn_slave_addr = 0x4B;
t_adn_connect_map con; t_adn_connect_map con;
t_adn_connect_cfg cfg; t_adn_connect_cfg cfg;
/* Disable UPDATE' pin by pulling it HIGH */ /* Disable UPDATE' pin by pulling it HIGH */
gpio_set_pin_dir(GPIO_ADN_UPDATE_PORT, GPIO_ADN_UPDATE_PIN, OUTPUT);
gpio_set_pin_state( GPIO_ADN_UPDATE_PORT, GPIO_ADN_UPDATE_PIN, HIGH); gpio_set_pin_state( GPIO_ADN_UPDATE_PORT, GPIO_ADN_UPDATE_PIN, HIGH);
if (afc_i2c_take_by_busid(I2C_BUS_CPU_ID, &i2c_bus_id, (TickType_t)100) == pdFALSE) { /* There's a delay circuit in the Reset pin of the clock switch, we must wait until it clears out */
gpio_set_pin_dir( GPIO_ADN_RESETN_PORT, GPIO_ADN_RESETN_PIN, INPUT);
while( gpio_read_pin( GPIO_ADN_RESETN_PORT, GPIO_ADN_RESETN_PIN ) == 0) {
vTaskDelay(50);
}
if (i2c_take_by_busid(I2C_BUS_CPU_ID, &i2c_bus_id, (TickType_t)10) == pdFALSE) {
return; return;
} }
/* Configure the interconnects */ /* Configure the interconnects */
con.out0 = 13; con.out0 = 0;
con.out1 = 14; con.out1 = 0;
con.out2 = 13; con.out2 = 0;
con.out3 = 12; con.out3 = 0;
con.out4 = 13; con.out4 = 13;
con.out5 = 8; con.out5 = 8;
con.out6 = 8; con.out6 = 8;
...@@ -51,7 +63,7 @@ void adn4604_setup(void) { ...@@ -51,7 +63,7 @@ void adn4604_setup(void) {
con.out10 = 14; con.out10 = 14;
con.out11 = 14; con.out11 = 14;
con.out12 = 14; con.out12 = 14;
con.out13 = 8; con.out13 = 5;
con.out14 = 14; con.out14 = 14;
con.out15 = 14; con.out15 = 14;
...@@ -66,13 +78,13 @@ void adn4604_setup(void) { ...@@ -66,13 +78,13 @@ void adn4604_setup(void) {
xI2CMasterWrite( i2c_bus_id, adn_slave_addr, map_sel, sizeof(map_sel) ); xI2CMasterWrite( i2c_bus_id, adn_slave_addr, map_sel, sizeof(map_sel) );
/* Enable desired outputs */ /* Enable desired outputs */
for (uint8_t i = 4; i <= 15; i++) { for (uint8_t i = 0; i < 16; i++) {
adn4604_tx_enable(i2c_bus_id, adn_slave_addr, i); adn4604_tx_enable(i2c_bus_id, adn_slave_addr, i);
} }
adn4604_update( i2c_bus_id, adn_slave_addr ); adn4604_update( i2c_bus_id, adn_slave_addr );
afc_i2c_give(i2c_bus_id); i2c_give(i2c_bus_id);
} }
void adn4604_tx_enable( uint8_t i2c_bus_id, uint8_t slave_addr, uint8_t output ) void adn4604_tx_enable( uint8_t i2c_bus_id, uint8_t slave_addr, uint8_t output )
......
/* /*
* adn4604.h * openMMC -- Open Source modular IPM Controller firmware
* *
* AFCIPMI -- * Copyright (C) 2015 Henrique Silva <henrique.silva@lnls.br>
*
* Copyright (C) 2015
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
...@@ -17,6 +15,8 @@ ...@@ -17,6 +15,8 @@
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* @license GPL-3.0+ <http://spdx.org/licenses/GPL-3.0+>
*/ */
#ifndef ADN4604_H_ #ifndef ADN4604_H_
......
/*
* openMMC -- Open Source modular IPM Controller firmware
*
* Copyright (C) 2015-2016 Henrique Silva <henrique.silva@lnls.br>
*
* 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 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* @license GPL-3.0+ <http://spdx.org/licenses/GPL-3.0+>
*/
#include "FreeRTOS.h" #include "FreeRTOS.h"
#include "task.h" #include "task.h"
#include "port.h" #include "port.h"
#include "fpga_spi.h" #include "fpga_spi.h"
#include "pin_mapping.h" #include "pin_mapping.h"
#include "task_priorities.h" #include "task_priorities.h"
#include "i2c.h"
#include "string.h" #include "string.h"
#include "led.h" #include "led.h"
#include "board_version.h"
#define FPGA_SPI_BITRATE 10000000
#define FPGA_SPI_FRAME_SIZE 8
/* Write one byte on the specified address on the FPGA RAM */ /* Write one byte on the specified address on the FPGA RAM */
static void write_fpga_byte( uint32_t data, uint32_t address ) static void write_fpga_byte( uint16_t address, uint32_t data )
{ {
uint8_t tx_buff[7]; uint8_t tx_buff[7];
tx_buff[0] = WR_COMMAND; tx_buff[0] = WR_COMMAND;
tx_buff[1] = 0x00; tx_buff[1] = (address >> 8) & 0xFF;
tx_buff[2] = address; tx_buff[2] = address & 0xFF;
tx_buff[3] = ( ( data >> 24) & 0xff ); tx_buff[3] = ( ( data >> 24) & 0xFF );
tx_buff[4] = ( ( data >> 16) & 0xff ); tx_buff[4] = ( ( data >> 16) & 0xFF );
tx_buff[5] = ( ( data >> 8) & 0xff ); tx_buff[5] = ( ( data >> 8) & 0xFF );
tx_buff[6] = ( data & 0xff ); tx_buff[6] = ( data & 0xFF );
ssp_write( FPGA_SPI, tx_buff, sizeof(tx_buff)/sizeof(tx_buff[0]) ); ssp_write( FPGA_SPI, tx_buff, sizeof(tx_buff) );
}
static void write_fpga_buffer( t_board_diagnostic diag )
{
uint16_t i;
/* Send all bytes sequentially, except the last, whose address is different (0xFF) */
for( i = 0; i < ((sizeof(diag.buffer)/sizeof(diag.buffer[0]))- 1); i++) {
write_fpga_byte( i, diag.buffer[i] );
}
write_fpga_byte( diag.buffer[i] , 0xFF );
} }
/* Read one byte from the specified address on the FPGA RAM */ /* Read one byte from the specified address on the FPGA RAM */
static uint32_t read_fpga_byte( uint32_t address ) static uint32_t read_fpga_byte( uint16_t address )
{ {
uint8_t tx_buff[3]; uint8_t tx_buff[3];
uint8_t rx_buff[7]; uint8_t rx_buff[7];
tx_buff[0] = RD_COMMAND; tx_buff[0] = RD_COMMAND;
tx_buff[1] = 0x00; tx_buff[1] = (address >> 8) & 0xFF;
tx_buff[2] = address; tx_buff[2] = address & 0xFF;
ssp_write_read( FPGA_SPI, tx_buff, sizeof(tx_buff), rx_buff, sizeof(rx_buff)-sizeof(tx_buff) ); ssp_write_read( FPGA_SPI, &tx_buff[0], sizeof(tx_buff), &rx_buff[0], sizeof(rx_buff), portMAX_DELAY );
return ( (uint32_t) ( (rx_buff[3] << 24) | (rx_buff[4] << 16) | (rx_buff[5] << 8) | rx_buff[6] ) ); return ( (rx_buff[3] << 24) | (rx_buff[4] << 16) | (rx_buff[5] << 8) | rx_buff[6]);
} }
static void write_fpga_buffer( t_board_diagnostic diag ) static void read_fpga_buffer( uint32_t * buffer, uint32_t buffer_len )
{ {
uint16_t i; for (uint8_t i = 0; i < buffer_len; i++) {
/* Send all bytes sequentially, except the last, whose address is different (0xFF) */ buffer[i] = read_fpga_byte(i);
for( i = 0; i < (sizeof(diag.buffer)/sizeof(diag.buffer[0])- 1); i++) { }
write_fpga_byte( diag.buffer[i], i ); }
static void init_diag_struct( board_diagnostic * diag )
{
uint8_t i,j;
/* Card ID */
diag->cardID[0] = 0;
diag->cardID[1] = 0;
diag->cardID[2] = 0;
diag->cardID[3] = 0;
/* AMC IPMI address */
diag->ipmi_addr = ipmb_addr;
/* AMC Slot Number */
diag->slot_id = (ipmb_addr-0x70)/2;
/* Data Valid */
/* Indicates that LPC is transfering data */
diag->data_valid = 0x55555555;
/* Sensors Readings */
for (i = 0, j = 0; i <= NUM_SENSOR; i++) {
if (sensor_array[i].diag_devID != NO_DIAG) {
diag->sensor[j].dev_id = sensor_array[i].diag_devID;
diag->sensor[j].measure = sensor_array[i].readout_value;
j++;
}
} }
write_fpga_byte( diag.buffer[i+1] , 0xFF );
diag->fmc_slot.fmc2_pg_c2m = gpio_read_pin( 1, 19 );
diag->fmc_slot.fmc1_pg_c2m = gpio_read_pin( 1, 18 );
diag->fmc_slot.fmc2_pg_m2c = gpio_read_pin( 1, 17 );
diag->fmc_slot.fmc1_pg_m2c = gpio_read_pin( 1, 16 );
diag->fmc_slot.fmc2_prsnt_m2c_n = gpio_read_pin( 1, 15 );
diag->fmc_slot.fmc2_prsnt_m2c_n = gpio_read_pin( 1, 14 );
} }
/* Send board data to the FPGA RAM via SPI periodically */ /* Send board data to the FPGA RAM via SPI periodically */
...@@ -54,8 +122,7 @@ void vTaskFPGA_COMM( void * Parameters ) ...@@ -54,8 +122,7 @@ void vTaskFPGA_COMM( void * Parameters )
{ {
t_board_diagnostic diag_struct; t_board_diagnostic diag_struct;
board_diagnostic * diag = &(diag_struct.info); board_diagnostic * diag = &(diag_struct.info);
uint32_t rx_trace[FPGA_MEM_ADDR_MAX+1] = {0}; uint32_t rx_trace[FPGA_MEM_ADDR_MAX] = {0};
uint32_t data;
/* Zero fill the diag struct */ /* Zero fill the diag struct */
memset( &(diag_struct.buffer[0]), 0, sizeof(diag_struct.buffer)); memset( &(diag_struct.buffer[0]), 0, sizeof(diag_struct.buffer));
...@@ -63,14 +130,18 @@ void vTaskFPGA_COMM( void * Parameters ) ...@@ -63,14 +130,18 @@ void vTaskFPGA_COMM( void * Parameters )
/* Initialize diagnostic struct with known data */ /* Initialize diagnostic struct with known data */
init_diag_struct( diag ); init_diag_struct( diag );
for ( ;; ) { /* Check if the FPGA has finished programming itself from the FLASH */
while (!gpio_read_pin( GPIO_DONE_B_PORT, GPIO_DONE_B_PIN)) {
vTaskDelay(FPGA_UPDATE_RATE);
}
if (board_info.board_version == BOARD_VERSION_AFC_V3_1) {
gpio_set_pin_state(0, 19, HIGH);
}
/* Check if the FPGA has finished programming itself from the FLASH */ ssp_init( FPGA_SPI, FPGA_SPI_BITRATE, FPGA_SPI_FRAME_SIZE, SSP_MASTER, SSP_POLLING );
while (!gpio_read_pin( GPIO_DONE_B_PORT, GPIO_DONE_B_PIN)) {
vTaskDelay(FPGA_UPDATE_RATE);
}
for ( ;; ) {
/* Update diagnostic struct information */ /* Update diagnostic struct information */
/* Data Valid byte - indicates that LPC is transferring data */ /* Data Valid byte - indicates that LPC is transferring data */
...@@ -80,7 +151,7 @@ void vTaskFPGA_COMM( void * Parameters ) ...@@ -80,7 +151,7 @@ void vTaskFPGA_COMM( void * Parameters )
for (uint8_t i = 0, j = 0; i <= NUM_SENSOR; i++) { for (uint8_t i = 0, j = 0; i <= NUM_SENSOR; i++) {
if (sensor_array[i].diag_devID != NO_DIAG) { if (sensor_array[i].diag_devID != NO_DIAG) {
diag->sensor[j].dev_id = sensor_array[i].diag_devID; diag->sensor[j].dev_id = sensor_array[i].diag_devID;
diag->sensor[j].measure = sensor_array[i].data->readout_value; diag->sensor[j].measure = sensor_array[i].readout_value;
j++; j++;
} }
} }
...@@ -94,85 +165,32 @@ void vTaskFPGA_COMM( void * Parameters ) ...@@ -94,85 +165,32 @@ void vTaskFPGA_COMM( void * Parameters )
write_fpga_buffer( diag_struct ); write_fpga_buffer( diag_struct );
/* Read the buffer from the FPGA to check eventual corruptions */ read_fpga_buffer( &rx_trace[0], sizeof(rx_trace)/sizeof(rx_trace[0]) );
for( uint32_t addressFPGAram = 0; addressFPGAram < FPGA_MEM_ADDR_MAX; addressFPGAram++ ) {
rx_trace[addressFPGAram] = read_fpga_byte(addressFPGAram); /* BUG: The SSP interface keeps returning 0 when trying to read the
} * data from the FPGA, despite the fact that the waveform shows it's
* being returned correctly */
if( !cmpBuffs( &(diag_struct.buffer[0]), sizeof(diag_struct.buffer)/sizeof(diag_struct.buffer[0]), &rx_trace[0], sizeof(rx_trace)/sizeof(rx_trace[0]) ) ) { #if SSP_TESTS
uint32_t data;
if( cmpBuffs( &(diag_struct.buffer[0]), sizeof(diag_struct.buffer)/sizeof(diag_struct.buffer[0]), &rx_trace[0], sizeof(rx_trace)/sizeof(rx_trace[0]) != 0 ) ) {
data = 0xAAAAAAAA; data = 0xAAAAAAAA;
extern const LED_activity_desc_t LED_2Hz_Blink_Activity; extern const LED_activity_desc_t LED_2Hz_Blink_Activity;
LED_update(LED_RED, &LED_2Hz_Blink_Activity); LED_update(LED_RED, &LED_2Hz_Blink_Activity);
} else { } else {
data = 0x55555555; data = 0x55555555;
extern const LED_activity_desc_t LED_Off_Activity; extern const LED_activity_desc_t LED_Off_Activity;
LED_update(LED_RED, &LED_Off_Activity); LED_update(LED_RED, &LED_Off_Activity);
} }
write_fpga_byte( data, 0x05 ); write_fpga_byte( 0x05, data );
#endif
vTaskDelay(FPGA_UPDATE_RATE); vTaskDelay(FPGA_UPDATE_RATE);
} }
} }
void init_fpga_spi( void ) void init_fpga_spi( void )
{ {
ssp_config( FPGA_SPI, FPGA_BITRATE, 8, true, false );
xTaskCreate(vTaskFPGA_COMM, "FPGA_COMM", 450, NULL, tskFPGA_COMM_PRIORITY, (TaskHandle_t *) NULL); xTaskCreate(vTaskFPGA_COMM, "FPGA_COMM", 450, NULL, tskFPGA_COMM_PRIORITY, (TaskHandle_t *) NULL);
} }
void init_diag_struct( board_diagnostic * diag )
{
uint8_t i,j;
/* Card ID */
diag->cardID[0] = 0;
diag->cardID[1] = 0;
diag->cardID[2] = 0;
diag->cardID[3] = 0;
/* AMC IPMI address */
diag->ipmi_addr = ipmb_addr;
/* AMC Slot Number */
diag->slot_id = (ipmb_addr-0x70)/2;
/* Data Valid */
/* Indicates that LPC is transfering data */
diag->data_valid = 0x55555555;
/* Sensors Readings */
for (i = 0, j = 0; i <= NUM_SENSOR; i++) {
if (sensor_array[i].diag_devID != NO_DIAG) {
diag->sensor[j].dev_id = sensor_array[i].diag_devID;
diag->sensor[j].measure = sensor_array[i].data->readout_value;
j++;
}
}
diag->fmc_slot.fmc2_pg_c2m = gpio_read_pin( 1, 19 );
diag->fmc_slot.fmc1_pg_c2m = gpio_read_pin( 1, 18 );
diag->fmc_slot.fmc2_pg_m2c = gpio_read_pin( 1, 17 );
diag->fmc_slot.fmc1_pg_m2c = gpio_read_pin( 1, 16 );
diag->fmc_slot.fmc2_prsnt_m2c_n = gpio_read_pin( 1, 15 );
diag->fmc_slot.fmc2_prsnt_m2c_n = gpio_read_pin( 1, 14 );
}
/* Compare two buffers' size and data
* Returns 0 if equal, 0xFF if different */
uint8_t cmpBuffs( uint32_t *bufa, uint32_t len_a, uint32_t *bufb, uint32_t len_b )
{
uint16_t i;
if (len_a != len_b) {
return 0xFF;
}
for( i = 0; i<len_a; i++ ) {
if( *bufa != *bufb ) {
return (0xFF);
}
bufa++;
bufb++;
}
return (0);
}
/*
* openMMC -- Open Source modular IPM Controller firmware
*
* Copyright (C) 2015-2016 Henrique Silva <henrique.silva@lnls.br>
*
* 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 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* @license GPL-3.0+ <http://spdx.org/licenses/GPL-3.0+>
*/
#ifndef FPGA_SPI_H_
#define FPGA_SPI_H_
#include "sdr.h"
#include "utils.h"
#define FPGA_UPDATE_RATE 5000 // in ms
#define FPGA_MEM_ADDR_MAX 0xFF
#define WR_COMMAND 0x80
#define RD_COMMAND 0x00
#define NO_DIAG 0x00
#define FPGA_TEMP_DEVID 0x01
#define FMC1_TEMP_DEVID 0x02
#define FMC2_TEMP_DEVID 0x03
#define DCDC_TEMP_DEVID 0x04
#define RAM_TEMP_DEVID 0x05
#define FMC1_12V_CURR_DEVID 0x06
#define FMC1_P3V3_CURR_DEVID 0x07
#define FMC1_VADJ_CURR_DEVID 0x08
#define FMC2_12V_CURR_DEVID 0x09
#define FMC2_P3V3_CURR_DEVID 0x0A
#define FMC2_VADJ_CURR_DEVID 0x0B
#define FMC1_12V_DEVID 0x0C
#define FMC1_P3V3_DEVID 0x0D
#define FMC1_VADJ_DEVID 0x0E
#define FMC2_12V_DEVID 0x0F
#define FMC2_P3V3_DEVID 0x10
#define FMC2_VADJ_DEVID 0x11
typedef struct {
#ifdef BF_MS_FIRST
uint8_t dev_id;
uint32_t measure:24;
#else
uint32_t measure:24;
uint8_t dev_id;
#endif
} t_sensor_diag;
typedef struct __attribute__ ((__packed__)) {
#ifdef BF_MS_FIRST
uint32_t reserved:26,
fmc2_pg_c2m:1,
fmc1_pg_c2m:1,
fmc2_pg_m2c:1,
fmc1_pg_m2c:1,
fmc2_prsnt_m2c_n:1,
fmc1_prsnt_m2c_n:1;
#else
uint32_t fmc1_prsnt_m2c_n:1,
fmc2_prsnt_m2c_n:1,
fmc1_pg_m2c:1,
fmc2_pg_m2c:1,
fmc1_pg_c2m:1,
fmc2_pg_c2m:1,
reserved:26;
#endif
} t_fmc_diag;
/* AFC diagnostic struct sent to FPGA via SPI */
typedef struct __attribute__ ((__packed__)) {
uint32_t cardID[4];
uint32_t slot_id:16,
ipmi_addr:16;
uint32_t data_valid;
t_sensor_diag sensor[NUM_SENSOR];
t_fmc_diag fmc_slot;
} board_diagnostic;
typedef union {
board_diagnostic info;
uint32_t buffer[sizeof(board_diagnostic)/sizeof(uint32_t)];
} t_board_diagnostic;
void vTaskFPGA_COMM( void * Parameters );
void init_fpga_spi( void );
#endif
/*
* openMMC -- Open Source modular IPM Controller firmware
*
* Copyright (C) 2015-2016 Henrique Silva <henrique.silva@lnls.br>
*
* 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 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* @license GPL-3.0+ <http://spdx.org/licenses/GPL-3.0+>
*/
#include "port.h" #include "port.h"
#include "jtag.h" #include "jtag.h"
......
/*
* openMMC -- Open Source modular IPM Controller firmware
*
* Copyright (C) 2015-2016 Henrique Silva <henrique.silva@lnls.br>
*
* 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 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* @license GPL-3.0+ <http://spdx.org/licenses/GPL-3.0+>
*/
#ifndef JTAG_H_
#define JTAG_H_
#define SCANSTA_PORT 2
#define SCANSTA_ADDR0_PIN 0
#define SCANSTA_ADDR1_PIN 1
#define SCANSTA_ADDR2_PIN 2
#define SCANSTA_ADDR3_PIN 3
#define SCANSTA_ADDR4_PIN 4
#define SCANSTA_ADDR5_PIN 5
#define SCANSTA_ADDR6_PIN 6
#define SCANSTA_RST_PIN 7
void init_scansta( void );
#endif
...@@ -77,15 +77,15 @@ ...@@ -77,15 +77,15 @@
#define GPIO_EN_P1V8_PORT 0 #define GPIO_EN_P1V8_PORT 0
#define GPIO_EN_P1V8_PIN 24 #define GPIO_EN_P1V8_PIN 24
#define GPIO_EM_FMC1_P12V_PORT 0 #define GPIO_EN_FMC1_P12V_PORT 0
#define GPIO_EM_FMC1_P12V_PIN 4 #define GPIO_EN_FMC1_P12V_PIN 4
#define GPIO_EN_FMC1_P3V3_PORT 0 #define GPIO_EN_FMC1_P3V3_PORT 0
#define GPIO_EN_FMC1_P3V3_PIN 25 #define GPIO_EN_FMC1_P3V3_PIN 25
#define GPIO_EN_FMC1_PVADJ_PORT 1 #define GPIO_EN_FMC1_PVADJ_PORT 1
#define GPIO_EN_FMC1_PVADJ_PIN 31 #define GPIO_EN_FMC1_PVADJ_PIN 31
#define GPIO_EM_FMC2_P12V_PORT 0 #define GPIO_EN_FMC2_P12V_PORT 0
#define GPIO_EM_FMC2_P12V_PIN 5 #define GPIO_EN_FMC2_P12V_PIN 5
#define GPIO_EN_FMC2_P3V3_PORT 0 #define GPIO_EN_FMC2_P3V3_PORT 0
#define GPIO_EN_FMC2_P3V3_PIN 26 #define GPIO_EN_FMC2_P3V3_PIN 26
#define GPIO_EN_FMC2_PVADJ_PORT 1 #define GPIO_EN_FMC2_PVADJ_PORT 1
...@@ -98,12 +98,14 @@ ...@@ -98,12 +98,14 @@
#define GPIO_EN_P1V0_PORT 3 #define GPIO_EN_P1V0_PORT 3
#define GPIO_EN_P1V0_PIN 25 #define GPIO_EN_P1V0_PIN 25
#define GPIO_PROGRAM_B_PIN 17
#define GPIO_PROGRAM_B_PORT 0 #define GPIO_PROGRAM_B_PORT 0
#define GPIO_DONE_B_PIN 22 #define GPIO_PROGRAM_B_PIN 17
#define GPIO_DONE_B_PORT 0 #define GPIO_DONE_B_PORT 0
#define GPIO_PGOOD_P1V0_PIN 26 #define GPIO_DONE_B_PIN 22
#define GPIO_FPGA_RESET_PORT 2
#define GPIO_FPGA_RESET_PIN 9
#define GPIO_PGOOD_P1V0_PORT 3 #define GPIO_PGOOD_P1V0_PORT 3
#define GPIO_PGOOD_P1V0_PIN 26
#define GPIO_DAC_VADJ_RST_PORT 0 #define GPIO_DAC_VADJ_RST_PORT 0
#define GPIO_DAC_VADJ_RST_PIN 21 #define GPIO_DAC_VADJ_RST_PIN 21
...@@ -112,6 +114,8 @@ ...@@ -112,6 +114,8 @@
#define GPIO_ADN_UPDATE_PORT 1 #define GPIO_ADN_UPDATE_PORT 1
#define GPIO_ADN_UPDATE_PIN 26 #define GPIO_ADN_UPDATE_PIN 26
#define GPIO_ADN_RESETN_PORT 1
#define GPIO_ADN_RESETN_PIN 22
#endif #endif
......
/*
* openMMC -- Open Source modular IPM Controller firmware
*
* Copyright (C) 2015 Julian Mendez <julian.mendez@cern.ch>
* Copyright (C) 2015-2016 Henrique Silva <henrique.silva@lnls.br>
*
* 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 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* @license GPL-3.0+ <http://spdx.org/licenses/GPL-3.0+>
*/
#include "fru.h" #include "fru.h"
/********************************************* /*********************************************
...@@ -33,8 +55,8 @@ ...@@ -33,8 +55,8 @@
*********************************************/ *********************************************/
#define AMC_POINT_TO_POINT_RECORD_CNT 2 #define AMC_POINT_TO_POINT_RECORD_CNT 2
#define AMC_POINT_TO_POINT_RECORD_LIST \ #define AMC_POINT_TO_POINT_RECORD_LIST \
GENERIC_POINT_TO_POINT_RECORD(0, PORT(4), PORT(5), PORT(6), PORT(7), PCIE, GEN1_NO_SSC, MATCHES_10); \ GENERIC_POINT_TO_POINT_RECORD(0, PORT(4), PORT(5), PORT(6), PORT(7), PCIE, GEN1_NO_SSC, MATCHES_01); \
GENERIC_POINT_TO_POINT_RECORD(1, PORT(8), PORT(9), PORT(10), PORT(11), PCIE, GEN1_NO_SSC, MATCHES_10); GENERIC_POINT_TO_POINT_RECORD(1, PORT(8), PORT(9), PORT(10), PORT(11), PCIE, GEN1_NO_SSC, MATCHES_01);
/********************************************* /*********************************************
* AMC: Point to point clock record * AMC: Point to point clock record
......
message(STATUS "Selected Controller: ${TARGET_CONTROLLER}")
if(${TARGET_CONTROLLER} MATCHES "^(lpc|LPC)17")
set(LPC17XX_PATH ${CMAKE_CURRENT_SOURCE_DIR}/nxp/lpc17xx)
set(LPCOPEN_SRCPATH ${LPC17XX_PATH}/lpcopen/src)
set(LPCOPEN_INCPATH ${LPC17XX_PATH}/lpcopen/inc)
include_directories(${LPC17XX_PATH})
set(PROJ_SRCS ${PROJ_SRCS}
${LPC17XX_PATH}/lpc17_i2c.c
${LPC17XX_PATH}/lpc17_spi.c
${LPC17XX_PATH}/lpc17_ssp.c
${LPC17XX_PATH}/lpc17_hpm.c
)
set(LPC17_SRCS ${LPC17_SRCS}
${LPC17XX_PATH}/sysinit.c
${LPC17XX_PATH}/cr_startup_lpc175x_6x.c
)
set(PROJ_HDRS ${PROJ_HDRS}
${LPC17XX_PATH}
${LPCOPEN_INCPATH}
)
set(LIBLPCOPEN_SRCS
${LPCOPEN_SRCPATH}/chip_17xx_40xx.c
${LPCOPEN_SRCPATH}/clock_17xx_40xx.c
${LPCOPEN_SRCPATH}/gpio_17xx_40xx.c
${LPCOPEN_SRCPATH}/gpioint_17xx_40xx.c
${LPCOPEN_SRCPATH}/i2c_17xx_40xx.c
${LPCOPEN_SRCPATH}/iap.c
${LPCOPEN_SRCPATH}/iocon_17xx_40xx.c
${LPCOPEN_SRCPATH}/spi_17xx_40xx.c
${LPCOPEN_SRCPATH}/ssp_17xx_40xx.c
${LPCOPEN_SRCPATH}/sysctl_17xx_40xx.c
${LPCOPEN_SRCPATH}/sysinit_17xx_40xx.c
${LPCOPEN_SRCPATH}/timer_17xx_40xx.c
${LPCOPEN_SRCPATH}/uart_17xx_40xx.c
${LPCOPEN_SRCPATH}/wwdt_17xx_40xx.c
)
include_directories(${LPCOPEN_INCPATH})
set(LPC17_SRCS ${LPC17_SRCS} PARENT_SCOPE)
set(TARGET_ARCH "armv7-m" )
set(TARGET_CPU "cortex-m3")
set(LPC17_FLAGS ${LPC17_FLAGS} -D__CODE_RED)
set(LPC17_FLAGS ${LPC17_FLAGS} -DCORE_M3)
set(LPC17_FLAGS ${LPC17_FLAGS} -D__USE_LPCOPEN)
set(LPC17_FLAGS ${LPC17_FLAGS} -DNO_BOARD_LIB)
set(LPC17_FLAGS ${LPC17_FLAGS} -D__NEWLIB__)
set(LPC17_FLAGS ${LPC17_FLAGS} -D__LPC17XX__)
set(LPC17_FLAGS ${LPC17_FLAGS} -mcpu=${TARGET_CPU} -mtune=${TARGET_CPU})
set(LPC17_FLAGS ${LPC17_FLAGS} -march=${TARGET_ARCH})
set(LPC17_FLAGS ${LPC17_FLAGS} -mthumb -mthumb-interwork -mno-sched-prolog -mapcs-frame)
string(REGEX REPLACE ";" " " LPC17_FLAGS "${LPC17_FLAGS}")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${LPC17_FLAGS}")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS}" PARENT_SCOPE)
add_library(lpcopen STATIC ${LIBLPCOPEN_SRCS})
endif()
set(PROJ_SRCS ${PROJ_SRCS} PARENT_SCOPE)
set(PROJ_HDRS ${PROJ_HDRS} PARENT_SCOPE)
/* /*
* AFCIPMI -- * openMMC --
* *
* Copyright (C) 2015 Henrique Silva <henrique.silva@lnls.br> * Copyright (C) 2015 Henrique Silva <henrique.silva@lnls.br>
* *
...@@ -37,6 +37,7 @@ ...@@ -37,6 +37,7 @@
#define LOW 0 #define LOW 0
#define HIGH 1 #define HIGH 1
#define gpio_init() Chip_GPIO_Init( LPC_GPIO )
#define gpio_read_pin( port, pin ) Chip_GPIO_GetPinState( LPC_GPIO, port, pin ) #define gpio_read_pin( port, pin ) Chip_GPIO_GetPinState( LPC_GPIO, port, pin )
#define gpio_read_port( port ) Chip_GPIO_GetPortValue( LPC_GPIO, port ) #define gpio_read_port( port ) Chip_GPIO_GetPortValue( LPC_GPIO, port )
#define gpio_set_pin( port, pin ) Chip_GPIO_SetPinOutHigh( LPC_GPIO, port, pin ) #define gpio_set_pin( port, pin ) Chip_GPIO_SetPinOutHigh( LPC_GPIO, port, pin )
......
/*
* AFCIPMI --
*
* Copyright (C) 2015 Henrique Silva <henrique.silva@lnls.br>
*
* 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 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*!
* @file lpc17_hpm.c
* @author Henrique Silva <henrique.silva@lnls.br>, LNLS
* @date March 2016
*
* @brief Firmware update functions (HPM.1)
*/
/* LPC17xx HPM Functions */
#include "chip_lpc175x_6x.h"
#include "lpc17_hpm.h"
#include "iap.h"
#include "ipmi.h"
#include "boot.h"
#ifdef MODULE_WATCHDOG
#include "watchdog.h"
#endif
uint32_t ipmc_page_addr = 0;
uint32_t ipmc_image_size = 0;
uint32_t ipmc_pg_index = 0;
uint32_t ipmc_page[64];
uint8_t ipmc_hpm_prepare_comp( void )
{
ipmc_image_size = 0;
ipmc_pg_index = 0;
ipmc_page_addr = 0;
for(uint32_t i=0; i<(sizeof(ipmc_page)/sizeof(uint32_t)); i++) {
ipmc_page[i] = 0xFFFFFFFF;
}
if (ipmc_erase_sector(IPMC_UPDATE_SECTOR_START, IPMC_UPDATE_SECTOR_END) != IAP_CMD_SUCCESS) {
return IPMI_CC_UNSPECIFIED_ERROR;
}
return IPMI_CC_OK;
}
uint8_t ipmc_hpm_upload_block( uint8_t * block, uint16_t size )
{
uint8_t remaining_bytes_start;
if ( sizeof(ipmc_page)/4 - ipmc_pg_index > size/4) {
/* Our page is not full yet, just append the new data */
for (uint16_t i =0; i < size; i+=4, ipmc_pg_index++) {
ipmc_page[ipmc_pg_index] = (block[i+3] << 24)|(block[i+2] << 16)|(block[i+1] << 8)|(block[i]);
}
return IPMI_CC_OK;
} else {
/* Complete the remaining bytes on the buffer */
remaining_bytes_start = (sizeof(ipmc_page)/4 - ipmc_pg_index)*4;
for (uint16_t i =0; ipmc_pg_index < sizeof(ipmc_page)/4 ; i+=4, ipmc_pg_index++) {
ipmc_page[ipmc_pg_index] = (block[i+3] << 24)|(block[i+2] << 16)|(block[i+1] << 8)|(block[i]);
}
/* Program the complete page in the Flash */
ipmc_program_page( ipmc_page_addr, ipmc_page, sizeof(ipmc_page));
/* Advance the address counter */
ipmc_page_addr += sizeof(ipmc_page);
ipmc_image_size += sizeof(ipmc_page);
/* Empty our buffer and reset the index */
for(uint32_t i=0; i<(sizeof(ipmc_page)/sizeof(uint32_t)); i++) {
ipmc_page[i] = 0xFFFFFFFF;
}
ipmc_pg_index = 0;
/* Save the trailing bytes */
for (uint8_t i =0; i <(size-remaining_bytes_start); i+=4) {
ipmc_page[ipmc_pg_index++] = (block[i+3+remaining_bytes_start] << 24)|(block[i+2+remaining_bytes_start] << 16)|(block[i+1+remaining_bytes_start] << 8)|(block[i+remaining_bytes_start]);
}
return IPMI_CC_COMMAND_IN_PROGRESS;
}
}
uint8_t ipmc_hpm_finish_upload( uint32_t image_size )
{
/* Check if the last page was already programmed */
if (ipmc_pg_index != 0) {
/* Program the complete page in the Flash */
ipmc_program_page( ipmc_page_addr, ipmc_page, sizeof(ipmc_page));
ipmc_image_size += ipmc_pg_index*4;
ipmc_pg_index = 0;
ipmc_page_addr = 0;
}
for(uint16_t i=0; i<(sizeof(ipmc_page)/sizeof(uint32_t)); i++) {
ipmc_page[i] = 0xFFFFFFFF;
}
/* BUG: This will overwrite the last page in the flash */
/* TODO: Write actual firmware ID */
ipmc_page[63] = 0x55555555;
ipmc_program_page( UPGRADE_FLASH_END_ADDR-IPMC_UPDATE_ADDRESS_OFFSET-256, ipmc_page, sizeof(ipmc_page));
if (ipmc_image_size != image_size) {
/* HPM CC: Number of bytes received does not match the size provided in the "Finish firmware upload" request */
return 0x81;
}
return IPMI_CC_OK;
}
uint8_t ipmc_hpm_get_upgrade_status( void )
{
/* The IAP commands run when they're called and block the firmware. Long commands would cause timeouts on the IPMB */
return IPMI_CC_OK;
}
uint8_t ipmc_hpm_activate_firmware( void )
{
/* Schedule a reset in the next watchdog task cycle, inhibiting the task to feed its counter */
#ifdef MODULE_WATCHDOG
watchdog_reset_mcu();
#endif
return IPMI_CC_OK;
}
uint8_t ipmc_program_page( uint32_t address, uint32_t * data, uint32_t size )
{
if (size % 256) {
/* Data should be a 256 byte boundary */
return IPMI_CC_PARAM_OUT_OF_RANGE;
}
portDISABLE_INTERRUPTS();
if (Chip_IAP_PreSectorForReadWrite( IPMC_UPDATE_SECTOR_START, IPMC_UPDATE_SECTOR_END ) != IAP_CMD_SUCCESS) {
portENABLE_INTERRUPTS();
return IPMI_CC_UNSPECIFIED_ERROR;
}
if (Chip_IAP_CopyRamToFlash( IPMC_UPDATE_ADDRESS_OFFSET + address, data, size )) {
portENABLE_INTERRUPTS();
return IPMI_CC_UNSPECIFIED_ERROR;
}
portENABLE_INTERRUPTS();
return IPMI_CC_OK;
}
uint8_t ipmc_erase_sector( uint32_t sector_start, uint32_t sector_end)
{
portDISABLE_INTERRUPTS();
if (Chip_IAP_PreSectorForReadWrite( sector_start, sector_end ) != IAP_CMD_SUCCESS) {
portENABLE_INTERRUPTS();
return IPMI_CC_UNSPECIFIED_ERROR;
}
if (Chip_IAP_EraseSector( sector_start, sector_end ) != IAP_CMD_SUCCESS) {
portENABLE_INTERRUPTS();
return IPMI_CC_UNSPECIFIED_ERROR;
}
portENABLE_INTERRUPTS();
return IPMI_CC_OK;
}
/*
* AFCIPMI --
*
* Copyright (C) 2015 Henrique Silva <henrique.silva@lnls.br>
*
* 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 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*!
* @file lpc17_hpm.h
* @author Henrique Silva <henrique.silva@lnls.br>, LNLS
* @date March 2016
*
* @brief Firmware update functions (HPM.1)
*/
#ifdef LPC17_HPM_H_
#undef LPC17_HPM_H_
#endif
#define LPC17_HPM_H_
#include "hpm.h"
uint8_t ipmc_hpm_prepare_comp( void );
uint8_t ipmc_hpm_upload_block( uint8_t * block, uint16_t size );
uint8_t ipmc_hpm_finish_upload( uint32_t image_size );
uint8_t ipmc_hpm_activate_firmware( void );
uint8_t ipmc_hpm_get_upgrade_status( void );
uint8_t ipmc_program_page( uint32_t address, uint32_t * data, uint32_t size );
uint8_t ipmc_erase_sector( uint32_t sector_start, uint32_t sector_end);
/*
* openMMC --
*
* Copyright (C) 2015 Henrique Silva <henrique.silva@lnls.br>
*
* 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 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*!
* @file lpc17_i2c.c
* @author Henrique Silva <henrique.silva@lnls.br>, LNLS
* @date March 2016
*
* @brief I2C driver for LPC17xx
*/
#include "port.h" #include "port.h"
#include "i2c.h"
#include "string.h" #include "string.h"
#include "board_version.h" #include "board_version.h"
...@@ -49,12 +75,12 @@ void Board_I2C_Init(I2C_ID_T id) ...@@ -49,12 +75,12 @@ void Board_I2C_Init(I2C_ID_T id)
Chip_IOCON_EnableOD(LPC_IOCON, 0, 0); Chip_IOCON_EnableOD(LPC_IOCON, 0, 0);
Chip_IOCON_EnableOD(LPC_IOCON, 0, 1); Chip_IOCON_EnableOD(LPC_IOCON, 0, 1);
if (afc_board_info.board_version == BOARD_VERSION_AFC_V3_1) { #ifndef BOARD_AFC_V3_1
Chip_IOCON_PinMux(LPC_IOCON, 0, 19, IOCON_MODE_INACT, IOCON_FUNC2); Chip_IOCON_PinMux(LPC_IOCON, 0, 19, IOCON_MODE_INACT, IOCON_FUNC2);
Chip_IOCON_PinMux(LPC_IOCON, 0, 20, IOCON_MODE_INACT, IOCON_FUNC2); Chip_IOCON_PinMux(LPC_IOCON, 0, 20, IOCON_MODE_INACT, IOCON_FUNC2);
Chip_IOCON_EnableOD(LPC_IOCON, 0, 19); Chip_IOCON_EnableOD(LPC_IOCON, 0, 19);
Chip_IOCON_EnableOD(LPC_IOCON, 0, 20); Chip_IOCON_EnableOD(LPC_IOCON, 0, 20);
} #endif
break; break;
case I2C2: case I2C2:
...@@ -101,7 +127,7 @@ I2C_XFER_T slave_cfg; ...@@ -101,7 +127,7 @@ I2C_XFER_T slave_cfg;
uint8_t recv_msg[i2cMAX_MSG_LENGTH]; uint8_t recv_msg[i2cMAX_MSG_LENGTH];
uint8_t recv_bytes; uint8_t recv_bytes;
uint8_t xI2CSlaveReceive( I2C_ID_T id, uint8_t * rx_buff, uint8_t buff_len, TickType_t timeout ) uint8_t xI2CSlaveReceive( I2C_ID_T id, uint8_t * rx_buff, uint8_t buff_len, uint32_t timeout )
{ {
uint8_t bytes_to_copy = 0; uint8_t bytes_to_copy = 0;
slave_task_id = xTaskGetCurrentTaskHandle(); slave_task_id = xTaskGetCurrentTaskHandle();
......
#include "FreeRTOS.h" /*
* openMMC --
*
* Copyright (C) 2015 Henrique Silva <henrique.silva@lnls.br>
*
* 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 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*!
* @file lpc17_i2c.h
* @author Henrique Silva <henrique.silva@lnls.br>, LNLS
* @date March 2016
*
* @brief I2C driver for LPC17xx
*/
/*! @brief Max message length (in bits) used in I2C */
#define i2cMAX_MSG_LENGTH 32
#define xI2CMasterWrite(id, addr, tx_buff, tx_len) Chip_I2C_MasterSend(id, addr, tx_buff, tx_len) #define xI2CMasterWrite(id, addr, tx_buff, tx_len) Chip_I2C_MasterSend(id, addr, tx_buff, tx_len)
#define xI2CMasterRead(id, addr, rx_buff, rx_len) Chip_I2C_MasterRead(id, addr, rx_buff, rx_len) #define xI2CMasterRead(id, addr, rx_buff, rx_len) Chip_I2C_MasterRead(id, addr, rx_buff, rx_len)
#define xI2CMasterWriteRead(id, addr, cmd, rx_buff, rx_len) Chip_I2C_MasterCmdRead(id, addr, cmd, rx_buff, rx_len) #define xI2CMasterWriteRead(id, addr, cmd, rx_buff, rx_len) Chip_I2C_MasterCmdRead(id, addr, cmd, rx_buff, rx_len)
uint8_t xI2CSlaveReceive( I2C_ID_T id, uint8_t * rx_buff, uint8_t buff_len, TickType_t timeout ); uint8_t xI2CSlaveReceive( I2C_ID_T id, uint8_t * rx_buff, uint8_t buff_len, uint32_t timeout );
void vI2CSlaveSetup ( I2C_ID_T id, uint8_t slave_addr ); void vI2CSlaveSetup ( I2C_ID_T id, uint8_t slave_addr );
void vI2CConfig( I2C_ID_T id, uint32_t speed ); void vI2CConfig( I2C_ID_T id, uint32_t speed );
/*
* openMMC --
*
* Copyright (C) 2015 Henrique Silva <henrique.silva@lnls.br>
*
* 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 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*!
* @file lpc17_interruptions.h
* @author Henrique Silva <henrique.silva@lnls.br>, LNLS
* @date March 2016
*
* @brief Interruptions control
*/
#ifdef PORT_INTERRUPTIONS_H_
#error Interruption functions already defined somewhere else! Aborting...
#else
#define PORT_INTERRUPTIONS_H_
#include "core_cm3.h"
#define irq_set_priority(irq, priority) NVIC_SetPriority( irq, priority )
#define irq_enable(irq) NVIC_EnableIRQ( irq )
#define irq_disable(irq) NVIC_DisableIRQ( irq )
#define irq_clear_pending(irq) NVIC_ClearPendingIRQ( irq )
#define irq_set_pending(irq) NVIC_SetPendingIRQ( irq )
#define irq_get_active(irq) NVIC_GetActive( irq )
#endif
/*
* openMMC --
*
* Copyright (C) 2015 Henrique Silva <henrique.silva@lnls.br>
*
* 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 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*!
* @file lpc17_power.h
* @author Henrique Silva <henrique.silva@lnls.br>, LNLS
* @date March 2016
*
* @brief Definitions of power mode selection for LPC17xx
*/
#ifdef LPC17_POWER_H_
#undef LPC17_POWER_H_
#endif
#define LPC17_POWER_H_
#include "pmu_17xx_40xx.h"
#define pm_sleep() Chip_PMU_Sleep(LPC_PMU, PMU_MCU_SLEEP)
#define pm_deep_sleep() Chip_PMU_Sleep(LPC_PMU, PMU_MCU_DEEP_SLEEP)
#define pm_power_down() Chip_PMU_Sleep(LPC_PMU, PMU_MCU_POWER_DOWN)
#define pm_deep_power_down() Chip_PMU_Sleep(LPC_PMU, PMU_MCU_DEEP_PWRDOWN)
/*
* openMMC --
*
* Copyright (C) 2015 Henrique Silva <henrique.silva@lnls.br>
*
* 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 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*!
* @file lpc17_spi.c
* @author Henrique Silva <henrique.silva@lnls.br>, LNLS
* @date March 2016
*
* @brief Legacy SPI driver for LPC17xx
*/
#include "port.h" #include "port.h"
#include "pin_mapping.h" #include "pin_mapping.h"
/* Private Functions */
void spi_pin_config( uint8_t id );
/*********************/
static bool spi_polling = false; static bool spi_polling = false;
static uint8_t frame_size = 8; static uint8_t frame_size = 8;
/* Assert SSEL pin */ /* Assert SSEL pin */
void spi_assertSSEL(void) void spi_assertSSEL(void)
{ {
Chip_GPIO_WritePortBit(LPC_GPIO, 0, 16, false); Chip_GPIO_SetPinState(LPC_GPIO, 0, 16, LOW);
} }
/* De-Assert SSEL pin */ /* De-Assert SSEL pin */
void spi_deassertSSEL(void) void spi_deassertSSEL(void)
{ {
Chip_GPIO_WritePortBit(LPC_GPIO, 0, 16, true); Chip_GPIO_SetPinState(LPC_GPIO, 0, 16, HIGH);
} }
void spi_config( uint32_t bitrate, uint8_t frame_sz, bool master_mode, bool poll ) void spi_config( uint32_t bitrate, uint8_t frame_sz, bool master_mode, bool poll )
...@@ -33,6 +56,8 @@ void spi_config( uint32_t bitrate, uint8_t frame_sz, bool master_mode, bool poll ...@@ -33,6 +56,8 @@ void spi_config( uint32_t bitrate, uint8_t frame_sz, bool master_mode, bool poll
Chip_IOCON_PinMux(LPC_IOCON, 0, 16, IOCON_MODE_PULLUP, IOCON_FUNC0); Chip_IOCON_PinMux(LPC_IOCON, 0, 16, IOCON_MODE_PULLUP, IOCON_FUNC0);
/* Pin 17 is used for PROGRAM_B, as we don't receive any data, the MISO pin is not used */ /* Pin 17 is used for PROGRAM_B, as we don't receive any data, the MISO pin is not used */
Chip_IOCON_PinMux(LPC_IOCON, 0, 18, IOCON_MODE_INACT, IOCON_FUNC3); Chip_IOCON_PinMux(LPC_IOCON, 0, 18, IOCON_MODE_INACT, IOCON_FUNC3);
gpio_set_pin_dir(0, 16, OUTPUT);
spi_deassertSSEL(); spi_deassertSSEL();
spi_init(LPC_SPI); spi_init(LPC_SPI);
...@@ -52,11 +77,10 @@ void spi_config( uint32_t bitrate, uint8_t frame_sz, bool master_mode, bool poll ...@@ -52,11 +77,10 @@ void spi_config( uint32_t bitrate, uint8_t frame_sz, bool master_mode, bool poll
} }
spi_flush_rx(LPC_SPI); spi_flush_rx(LPC_SPI);
} }
/* Buffer len in bytes */ /* Buffer len in bytes */
uint32_t spi_write( void * buffer, uint32_t buffer_len) uint32_t spi_write( uint8_t * buffer, uint32_t buffer_len)
{ {
SPI_DATA_SETUP_T data_st = {0}; SPI_DATA_SETUP_T data_st = {0};
...@@ -66,14 +90,14 @@ uint32_t spi_write( void * buffer, uint32_t buffer_len) ...@@ -66,14 +90,14 @@ uint32_t spi_write( void * buffer, uint32_t buffer_len)
Chip_SPI_RWFrames_Blocking( LPC_SPI, &data_st ); Chip_SPI_RWFrames_Blocking( LPC_SPI, &data_st );
return buffer_len; return buffer_len;
} else if ((!spi_polling) && (frame_size <= 8)) { } else if ((!spi_polling) && (frame_size <= 8)) {
data_st.pTxData = (uint8_t *)buffer; data_st.pTxData = buffer;
data_st.length = buffer_len; data_st.length = buffer_len;
Chip_SPI_Int_RWFrames8Bits( LPC_SPI, &data_st ); Chip_SPI_Int_RWFrames8Bits( LPC_SPI, &data_st );
/* BUG: We're not verifying if the message was trasmitted */ /* BUG: We're not verifying if the message was trasmitted */
return buffer_len; return buffer_len;
} else if ((!spi_polling) && (frame_size <= 16)) { } else if ((!spi_polling) && (frame_size <= 16)) {
data_st.pTxData = (uint8_t *)buffer; data_st.pTxData = buffer;
data_st.length = buffer_len; data_st.length = buffer_len;
Chip_SPI_Int_RWFrames16Bits( LPC_SPI, &data_st ); Chip_SPI_Int_RWFrames16Bits( LPC_SPI, &data_st );
/* BUG: We're not verifying if the message was trasmitted */ /* BUG: We're not verifying if the message was trasmitted */
...@@ -82,6 +106,8 @@ uint32_t spi_write( void * buffer, uint32_t buffer_len) ...@@ -82,6 +106,8 @@ uint32_t spi_write( void * buffer, uint32_t buffer_len)
return 0; return 0;
} }
/* WARNING: DO NOT USE! Functions not fully implemented and tested yet */
#if 0 #if 0
uint32_t spi_read( void * buffer, uint32_t buffer_len) uint32_t spi_read( void * buffer, uint32_t buffer_len)
{ {
......
/*
* openMMC --
*
* Copyright (C) 2015 Henrique Silva <henrique.silva@lnls.br>
*
* 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 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*!
* @file lpc17_spi.h
* @author Henrique Silva <henrique.silva@lnls.br>, LNLS
* @date March 2016
*
* @brief Legacy SPI driver definitions for LPC17xx
*/
#ifndef LPC17xx_SPI_H_ #ifndef LPC17xx_SPI_H_
#define LPC17xx_SPI_H_ #define LPC17xx_SPI_H_
...@@ -14,6 +41,7 @@ ...@@ -14,6 +41,7 @@
#define SPI_POLLING 1 #define SPI_POLLING 1
void spi_config( uint32_t bitrate, uint8_t frame_sz, bool master_mode, bool poll ); void spi_config( uint32_t bitrate, uint8_t frame_sz, bool master_mode, bool poll );
uint32_t spi_write( void * buffer, uint32_t buffer_len ); uint32_t spi_write( uint8_t * buffer, uint32_t buffer_len );
void spi_assertSSEL(void);
void spi_deassertSSEL(void);
#endif #endif
/*
* openMMC --
*
* Copyright (C) 2015 Henrique Silva <henrique.silva@lnls.br>
*
* 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 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*!
* @file lpc17_ssp.c
* @author Henrique Silva <henrique.silva@lnls.br>, LNLS
* @date March 2016
*
* @brief SSP driver for LPC17xx
*/
#include "port.h"
#include "string.h"
#include "pin_mapping.h"
const t_ssp_pin ssp_pins[MAX_SSP_INTERFACES] = {
[FPGA_SPI] = {
.port = 1,
.sck_pin = 20,
.sck_func = IOCON_FUNC3,
.ssel_pin = 21,
.ssel_func = IOCON_FUNC0,
.miso_pin = 23,
.miso_func = IOCON_FUNC3,
.mosi_pin = 24,
.mosi_func = IOCON_FUNC3,
},
[FLASH_SPI] = {
.port = 0,
.sck_pin = 7,
.sck_func = IOCON_FUNC2,
.ssel_pin = 6,
.ssel_func = IOCON_FUNC0,
.miso_pin = 8,
.miso_func = IOCON_FUNC2,
.mosi_pin = 9,
.mosi_func = IOCON_FUNC2,
},
[DAC_VADJ_SPI] = {
.port = 0,
.sck_pin = 15,
.sck_func = IOCON_FUNC2,
.ssel_pin = 16,
.ssel_func = IOCON_FUNC0,
/* Leave the MISO pin as GPIO as it's used for another purpose on the board */
.miso_pin = 17,
.miso_func = IOCON_FUNC0,
.mosi_pin = 18,
.mosi_func = IOCON_FUNC2,
}
};
static t_ssp_config ssp_cfg[MAX_SSP_INTERFACES] = {
[FPGA_SPI] = {
.lpc_id = LPC_SSP0,
.irq = SSP0_IRQn,
.pin_cfg = &ssp_pins[FPGA_SPI]
},
[FLASH_SPI] = {
.lpc_id = LPC_SSP1,
.irq = SSP1_IRQn,
.pin_cfg = &ssp_pins[FLASH_SPI]
},
[DAC_VADJ_SPI] = {
.lpc_id = LPC_SSP0,
.irq = SSP0_IRQn,
.pin_cfg = &ssp_pins[DAC_VADJ_SPI]
},
};
/* Maybe use semaphores to control the access to SSP0 */
uint8_t active_SSP0 = 0xFF;
static void ssp_irq_handler( LPC_SSP_T * ssp_id )
{
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
Chip_SSP_DATA_SETUP_T * xf_setup;
uint8_t ssp_cfg_index;
if ((ssp_id == LPC_SSP0) && (active_SSP0 != 0xFF)) {
ssp_cfg_index = active_SSP0;
} else if (ssp_id == LPC_SSP1) {
/* The only component in SPI1 is the Flash memory */
ssp_cfg_index = FLASH_SPI;
}
xf_setup = &ssp_cfg[ssp_cfg_index].xf_setup;
/* Disable SSP interrupts */
Chip_SSP_Int_Disable(ssp_id);
if (ssp_cfg[ssp_cfg_index].frame_size <= 8) {
Chip_SSP_Int_RWFrames8Bits(ssp_id, xf_setup);
}
else {
Chip_SSP_Int_RWFrames16Bits(ssp_id, xf_setup);
}
if ((xf_setup->rx_cnt != xf_setup->length) || (xf_setup->tx_cnt != xf_setup->length)) {
/* Enable ssp interrupts, we're going to read/write more data */
Chip_SSP_Int_Enable(ssp_id);
}
else {
/* Transfer is completed, notify the caller task */
vTaskNotifyGiveFromISR(ssp_cfg[ssp_cfg_index].caller_task, &xHigherPriorityTaskWoken);
/* Deassert SSEL pin */
ssp_ssel_control(ssp_cfg_index, DEASSERT);
}
portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
}
void SSP0_IRQHandler( void )
{
ssp_irq_handler(LPC_SSP0);
}
void SSP1_IRQHandler( void )
{
ssp_irq_handler(LPC_SSP1);
}
/*! @brief Function that controls the Slave Select (SSEL) signal
* This pin is controlled manually because the internal SSP driver resets the SSEL pin every 8 bits that are transfered
*/
void ssp_ssel_control( uint8_t id, t_ssel_state state )
{
gpio_set_pin_state( ssp_pins[id].port, ssp_pins[id].ssel_pin, state );
}
void ssp_init( uint8_t id, uint32_t bitrate, uint8_t frame_sz, bool master_mode, bool poll )
{
ssp_cfg[id].polling = poll;
ssp_cfg[id].frame_size = frame_sz;
ssp_cfg[id].master_mode = master_mode;
ssp_cfg[id].bitrate = bitrate;
/* Set up clock and muxing for SSP0/1 interface */
/* Slave Select (SSEL/FCS_B) is left as GPIO so we can send more than one byte without this pin going high (default operation of SSP interface) */
Chip_IOCON_Init(LPC_IOCON);
Chip_IOCON_PinMux(LPC_IOCON, ssp_pins[id].port, ssp_pins[id].sck_pin, IOCON_MODE_PULLDOWN, ssp_pins[id].sck_func);
Chip_IOCON_PinMux(LPC_IOCON, ssp_pins[id].port, ssp_pins[id].ssel_pin, IOCON_MODE_PULLUP, ssp_pins[id].ssel_func);
Chip_IOCON_PinMux(LPC_IOCON, ssp_pins[id].port, ssp_pins[id].mosi_pin, IOCON_MODE_INACT, ssp_pins[id].mosi_func);
Chip_IOCON_PinMux(LPC_IOCON, ssp_pins[id].port, ssp_pins[id].miso_pin, IOCON_MODE_INACT, ssp_pins[id].miso_func);
if (ssp_pins[id].ssel_func == 0) {
gpio_set_pin_dir( ssp_pins[id].port, ssp_pins[id].ssel_pin, OUTPUT);
gpio_set_pin_state( ssp_pins[id].port, ssp_pins[id].ssel_pin, HIGH);
}
Chip_SSP_Init(ssp_cfg[id].lpc_id);
Chip_SSP_SetBitRate(ssp_cfg[id].lpc_id, bitrate);
Chip_SSP_SetMaster(ssp_cfg[id].lpc_id, master_mode);
Chip_SSP_SetFormat(ssp_cfg[id].lpc_id, (frame_sz-1), SSP_FRAMEFORMAT_SPI, SSP_CLOCK_CPHA0_CPOL0);
Chip_SSP_Enable(ssp_cfg[id].lpc_id);
if (!poll) {
/* Configure interruption priority and enable it */
NVIC_SetPriority( ssp_cfg[id].irq, configMAX_SYSCALL_INTERRUPT_PRIORITY );
NVIC_EnableIRQ( ssp_cfg[id].irq );
}
if (ssp_cfg[id].lpc_id == LPC_SSP0) {
active_SSP0 = id;
}
}
uint8_t * tx_ssp;
uint8_t * rx_ssp;
void ssp_write_read( uint8_t id, uint8_t *tx_buf, uint32_t tx_len, uint8_t *rx_buf, uint32_t rx_len, uint32_t timeout )
{
Chip_SSP_DATA_SETUP_T * data_st = &ssp_cfg[id].xf_setup;
tx_ssp = pvPortMalloc(tx_len);
rx_ssp = pvPortMalloc(rx_len+tx_len);
memcpy(tx_ssp, tx_buf, tx_len);
ssp_cfg[id].caller_task = xTaskGetCurrentTaskHandle();
data_st->tx_cnt = 0;
data_st->rx_cnt = 0;
data_st->tx_data = tx_ssp;
data_st->rx_data = rx_ssp;
data_st->length = rx_len+tx_len;
/* Assert Slave Select pin to enable the transfer */
ssp_ssel_control(id, ASSERT);
if (ssp_cfg[id].polling) {
Chip_SSP_RWFrames_Blocking(ssp_cfg[id].lpc_id, data_st);
ssp_ssel_control(id, DEASSERT);
} else {
Chip_SSP_Int_FlushData(ssp_cfg[id].lpc_id);
/* Enable interrupt-based data transmission */
Chip_SSP_Int_Enable( ssp_cfg[id].lpc_id );
/* User defined timeout ? */
/* Wait until the transfer is finished */
ulTaskNotifyTake(pdTRUE, timeout);
}
if (rx_buf && rx_len > 0) {
memcpy(rx_buf, rx_ssp, rx_len+tx_len);
}
vPortFree(rx_ssp);
vPortFree(tx_ssp);
}
/*
* openMMC --
*
* Copyright (C) 2015 Henrique Silva <henrique.silva@lnls.br>
*
* 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 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*!
* @file lpc17_ssp.c
* @author Henrique Silva <henrique.silva@lnls.br>, LNLS
* @date March 2016
*
* @brief SSP driver definitions for LPC17xx
*/
#ifndef LPC17xx_SSP_H_
#define LPC17xx_SSP_H_
#include "chip_lpc175x_6x.h"
#include "ssp_17xx_40xx.h"
#include "FreeRTOS.h"
#include "task.h"
#define MAX_SSP_INTERFACES 3
#define SSP(n) LPC_SSP##n
#define SSP_SLAVE 0
#define SSP_MASTER 1
#define SSP_INTERRUPT 0
#define SSP_POLLING 1
typedef enum {
ASSERT = 0,
DEASSERT
} t_ssel_state;
typedef struct {
uint8_t port;
uint8_t sck_pin;
uint8_t sck_mode;
uint8_t sck_func;
uint8_t mosi_pin;
uint8_t mosi_mode;
uint8_t mosi_func;
uint8_t miso_pin;
uint8_t miso_mode;
uint8_t miso_func;
uint8_t ssel_pin;
uint8_t ssel_mode;
uint8_t ssel_func;
} t_ssp_pin;
typedef struct {
LPC_SSP_T * lpc_id;
IRQn_Type irq;
uint32_t bitrate;
uint8_t master_mode;
uint8_t polling;
uint8_t frame_size;
const t_ssp_pin * pin_cfg;
Chip_SSP_DATA_SETUP_T xf_setup;
TaskHandle_t caller_task;
} t_ssp_config;
void ssp_init( uint8_t id, uint32_t bitrate, uint8_t frame_sz, bool master_mode, bool poll );
void ssp_ssel_control( uint8_t id, t_ssel_state state );
void ssp_write_read( uint8_t id, uint8_t *tx_buf, uint32_t tx_len, uint8_t *rx_buf, uint32_t rx_len, uint32_t timeout );
#define ssp_chip_init(id) Chip_SSP_Init(SSP(id))
#define ssp_chip_deinit(id) Chip_SSP_DeInit(SSP(id))
#define ssp_flush_rx(id) Chip_SSP_Int_FlushData(SSP(id))
#define ssp_set_bitrate(id, bitrate) Chip_SSP_SetBitRate(SSP(id), bitrate)
#define ssp_write(id, buffer, buffer_len) ssp_write_read(id, buffer, buffer_len, NULL, 0, 0)
#define ssp_read(id, buffer, buffer_lenm, timeout) ssp_write_read(id, NULL, 0, buffer, buffer_len, timeout)
#endif
/*
* AFCIPMI --
*
* Copyright (C) 2015 Henrique Silva <henrique.silva@lnls.br>
*
* 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 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*!
* @file lpc17_watchdog.h
* @author Henrique Silva <henrique.silva@lnls.br>, LNLS
* @date December 2015
*
* @brief Definitions of Watchdog driver implementation for LPC17xx
*/
#ifdef LPC17_WATCHDOG_H_
#undef LPC17_WATCHDOG_H_
#endif
#define LPC17_WATCHDOG_H_
#include "wwdt_17xx_40xx.h"
#define wdt_init() Chip_WWDT_Init(LPC_WWDT)
#define wdt_start() Chip_WWDT_Start(LPC_WWDT)
#define wdt_config() Chip_WWDT_SetOption(LPC_WWDT, WWDT_WDMOD_WDRESET)
#define wdt_set_timeout( timeout ) Chip_WWDT_SetTimeOut(LPC_WWDT, timeout)
#define wdt_feed() Chip_WWDT_Feed(LPC_WWDT)
/*
* openMMC --
*
* Copyright (C) 2015 Henrique Silva <henrique.silva@lnls.br>
*
* 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 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*!
* @file port.h
* @author Henrique Silva <henrique.silva@lnls.br>, LNLS
* @date September 2015
*
* @brief Port layer (includes all portable functions headers)
*/
#ifndef PORT_H_
#define PORT_H_
/* List of all LPC17xx specific headers to be included */
#include "chip_lpc175x_6x.h"
#include "lpc17_gpio.h"
#include "lpc17_i2c.h"
#include "lpc17_ssp.h"
#include "lpc17_spi.h"
#include "lpc17_watchdog.h"
#include "lpc17_interruptions.h"
#include "lpc17_hpm.h"
#include "lpc17_power.h"
#endif
#include "port.h"
#include "pin_mapping.h"
/* Private Functions */
void ssp_pin_config( uint8_t id );
/*********************/
static bool ssp_polling = false;
static uint8_t frame_size = 8;
void ssp_config( uint8_t id, uint32_t bitrate, uint8_t frame_sz, bool master_mode, bool poll )
{
IRQn_Type irq;
LPC_SSP_T* ssp_id;
if (id == 0) {
ssp_id = LPC_SSP0;
} else {
ssp_id = LPC_SSP1;
}
ssp_polling = poll;
frame_size = frame_sz;
ssp_pin_config(id);
Chip_SSP_Init(ssp_id);
Chip_SSP_SetBitRate(ssp_id, bitrate);
Chip_SSP_SetMaster(ssp_id, master_mode);
Chip_SSP_SetFormat(ssp_id, (frame_sz-1), SSP_FRAMEFORMAT_SPI, SSP_CLOCK_CPHA0_CPOL0);
if (!poll) {
switch (id) {
case 0:
irq = SSP0_IRQn;
break;
case 1:
irq = SSP1_IRQn;
break;
}
NVIC_SetPriority( irq, configMAX_SYSCALL_INTERRUPT_PRIORITY );
NVIC_EnableIRQ( irq );
}
}
void ssp_pin_config( uint8_t id )
{
/* Set up clock and muxing for SSP0/1 interface */
switch( id ) {
case FPGA_SPI:
Chip_IOCON_PinMux(LPC_IOCON, 1, 20, IOCON_MODE_PULLDOWN, IOCON_FUNC3);
Chip_IOCON_PinMux(LPC_IOCON, 1, 21, IOCON_MODE_PULLUP, IOCON_FUNC3);
Chip_IOCON_PinMux(LPC_IOCON, 1, 23, IOCON_MODE_INACT, IOCON_FUNC3);
Chip_IOCON_PinMux(LPC_IOCON, 1, 24, IOCON_MODE_INACT, IOCON_FUNC3);
break;
case FLASH_SPI:
Chip_IOCON_PinMux(LPC_IOCON, 0, 6, IOCON_MODE_PULLDOWN, IOCON_FUNC3);
Chip_IOCON_PinMux(LPC_IOCON, 0, 7, IOCON_MODE_PULLUP, IOCON_FUNC3);
Chip_IOCON_PinMux(LPC_IOCON, 0, 8, IOCON_MODE_INACT, IOCON_FUNC3);
Chip_IOCON_PinMux(LPC_IOCON, 0, 9, IOCON_MODE_INACT, IOCON_FUNC3);
break;
case DAC_VADJ_SPI:
Chip_IOCON_PinMux(LPC_IOCON, 0, 15, IOCON_MODE_PULLDOWN, IOCON_FUNC3);
Chip_IOCON_PinMux(LPC_IOCON, 0, 16, IOCON_MODE_PULLUP, IOCON_FUNC3);
/* Pin 17 is used for PROGRAM_B, as we don't receive any data, the MISO pin is not used */
Chip_IOCON_PinMux(LPC_IOCON, 0, 18, IOCON_MODE_INACT, IOCON_FUNC3);
break;
}
}
/* Buffer len in bytes */
uint32_t ssp_write( uint8_t id, void * buffer, uint32_t buffer_len)
{
LPC_SSP_T* ssp_id;
switch( id ) {
case FPGA_SPI:
case DAC_VADJ_SPI:
ssp_id = LPC_SSP0;
break;
case FLASH_SPI:
ssp_id = LPC_SSP1;
break;
}
Chip_SSP_DATA_SETUP_T data_st = {0};
if (ssp_polling) {
return (Chip_SSP_WriteFrames_Blocking(ssp_id, (uint8_t *) buffer, buffer_len));
} else if ((!ssp_polling) && (frame_size <= 8)) {
data_st.tx_data = (uint8_t *)buffer;
data_st.length = buffer_len;
Chip_SSP_Int_RWFrames8Bits( ssp_id, &data_st );
/* BUG: We're not verifying if the message was trasmitted */
return buffer_len;
} else if ((!ssp_polling) && (frame_size <= 16)) {
data_st.tx_data = (uint16_t *)buffer;
data_st.length = buffer_len;
Chip_SSP_Int_RWFrames16Bits( ssp_id, &data_st );
/* BUG: We're not verifying if the message was trasmitted */
return buffer_len;
}
return 0;
}
uint32_t ssp_read( uint8_t id, void * buffer, uint32_t buffer_len)
{
LPC_SSP_T* ssp_id;
if (id == 0) {
ssp_id = LPC_SSP0;
} else {
ssp_id = LPC_SSP1;
}
Chip_SSP_DATA_SETUP_T data_st = {0};
if (ssp_polling) {
return (Chip_SSP_ReadFrames_Blocking(ssp_id, (uint8_t *) buffer, buffer_len));
} else if ((!ssp_polling) && (frame_size == 8)) {
data_st.tx_data = buffer;
data_st.length = buffer_len;
Chip_SSP_Int_RWFrames8Bits( ssp_id, &data_st );
/* BUG: We're not verifying if the message was trasmitted */
/* Bogus return */
return buffer_len;
} else if ((!ssp_polling) && (frame_size == 16)) {
data_st.tx_data = buffer;
data_st.length = buffer_len;
Chip_SSP_Int_RWFrames16Bits( ssp_id, &data_st );
/* BUG: We're not verifying if the message was trasmitted */
return buffer_len;
}
return 0;
}
uint32_t ssp_write_read( uint8_t id, uint8_t *tx_buf, uint8_t tx_len, uint8_t *rx_buf, uint8_t rx_len )
{
LPC_SSP_T* ssp_id;
if (id == 0) {
ssp_id = LPC_SSP0;
} else {
ssp_id = LPC_SSP1;
}
Chip_SSP_DATA_SETUP_T data_st = {0};
if (ssp_polling) {
data_st.tx_data = tx_buf;
data_st.rx_data = rx_buf;
data_st.length = tx_len+rx_len;
return (Chip_SSP_RWFrames_Blocking(ssp_id, &data_st));
} else if ((!ssp_polling) && (frame_size == 8)) {
data_st.tx_data = tx_buf;
data_st.length = tx_len;
Chip_SSP_Int_RWFrames8Bits( ssp_id, &data_st );
/* BUG: We're not verifying if the message was trasmitted */
/* Bogus return */
return rx_len;
} else if ((!ssp_polling) && (frame_size == 16)) {
data_st.tx_data = tx_buf;
data_st.length = tx_len;
Chip_SSP_Int_RWFrames16Bits( ssp_id, &data_st );
/* BUG: We're not verifying if the message was trasmitted */
return rx_len;
}
return 0;
}
#ifndef LPC17xx_SSP_H_
#define LPC17xx_SSP_H_
#include "chip_lpc175x_6x.h"
#include "ssp_17xx_40xx.h"
#define SSP(n) LPC_SSP##n
#define ssp_init(id) Chip_SSP_Init(SSP(id))
#define ssp_deinit(id) Chip_SSP_DeInit(SSP(id))
#define ssp_flush_rx(id) Chip_SSP_Int_FlushData(SSP(id))
#define ssp_set_bitrate(id, bitrate) Chip_SSP_SetBitRate(SSP(id), bitrate)
#define SSP_SLAVE 0
#define SSP_MASTER 1
#define SSP_INTERRUPT 0
#define SSP_POLLING 1
void ssp_config( uint8_t id, uint32_t bitrate, uint8_t frame_sz, bool master_mode, bool poll );
void ssp_pin_config( uint8_t id );
uint32_t ssp_write( uint8_t id, void * buffer, uint32_t buffer_len);
uint32_t ssp_read( uint8_t id, void * buffer, uint32_t buffer_len);
uint32_t ssp_write_read( uint8_t id, uint8_t *tx_buf, uint8_t tx_len, uint8_t *rx_buf, uint8_t rx_len );
#endif
#ifndef PORT_H_
#define PORT_H_
/* List of all LPC17xx specific headers to be included */
#include "chip_lpc175x_6x.h"
#include "lpc17_gpio.h"
#include "lpc17_i2c.h"
#include "lpc17_ssp.h"
#include "lpc17_spi.h"
#endif
include(CMakeForceCompiler)
set(CMAKE_SYSTEM_NAME Generic)
set(CMAKE_SYSTEM_VERSION 1)
# Set a toolchain path. You only need to set this if the toolchain isn't in
# your system path. Don't forget a trailing path separator!
set( TC_PATH "" )
# The toolchain prefix for all toolchain executables
set( CROSS_COMPILE arm-none-eabi- )
# specify the cross compiler. We force the compiler so that CMake doesn't
# attempt to build a simple test program as this will fail without us using
# the -nostartfiles option on the command line
cmake_force_c_compiler(${CROSS_COMPILE}gcc GNU)
cmake_force_cxx_compiler(${CROSS_COMPILE}g++ GNU)
# We must set the OBJCOPY setting into cache so that it's available to the
# whole project. Otherwise, this does not get set into the CACHE and therefore
# the build doesn't know what the OBJCOPY filepath is
set( CMAKE_OBJCOPY ${TC_PATH}${CROSS_COMPILE}objcopy
CACHE FILEPATH "The toolchain objcopy command " FORCE )
set(COMMON_FLAGS "-fno-builtin -ffunction-sections -fdata-sections -fno-strict-aliasing -fmessage-length=0")
set(CMAKE_C_FLAGS "${COMMON_FLAGS} -std=gnu99")
set(CMAKE_CXX_FLAGS "${COMMON_FLAGS} -std=gnu++0x")
set(CMAKE_EXE_LINKER_FLAGS "-Wl,-gc-sections --specs=nosys.specs -nostdlib -static -nostartfiles")
set(TRACE_PATH ${CMAKE_CURRENT_SOURCE_DIR})
set(PROJ_HDRS ${PROJ_HDRS} ${TRACE_PATH})
set(PROJ_SRCS ${PROJ_SRCS} ${TRACE_PATH}/trcBase.c
${TRACE_PATH}/trcHardwarePort.c
${TRACE_PATH}/trcKernel.c
${TRACE_PATH}/trcKernelPortFreeRTOS.c
${TRACE_PATH}/trcRecorder.c
${TRACE_PATH}/trcUser.c
)
set(PROJ_SRCS ${PROJ_SRCS} PARENT_SCOPE)
set(PROJ_HDRS ${PROJ_HDRS} PARENT_SCOPE)
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment