--- /dev/null
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>\r
+<?fileVersion 4.0.0?><cproject storage_type_id="org.eclipse.cdt.core.XmlProjectDescriptionStorage">\r
+ <storageModule moduleId="org.eclipse.cdt.core.settings">\r
+ <cconfiguration id="ilg.gnumcueclipse.managedbuild.cross.riscv.config.elf.debug.2049051127">\r
+ <storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="ilg.gnumcueclipse.managedbuild.cross.riscv.config.elf.debug.2049051127" moduleId="org.eclipse.cdt.core.settings" name="Debug">\r
+ <externalSettings/>\r
+ <extensions>\r
+ <extension id="org.eclipse.cdt.core.ELF" point="org.eclipse.cdt.core.BinaryParser"/>\r
+ <extension id="org.eclipse.cdt.core.GASErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>\r
+ <extension id="org.eclipse.cdt.core.GmakeErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>\r
+ <extension id="org.eclipse.cdt.core.GLDErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>\r
+ <extension id="org.eclipse.cdt.core.CWDLocator" point="org.eclipse.cdt.core.ErrorParser"/>\r
+ <extension id="org.eclipse.cdt.core.GCCErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>\r
+ </extensions>\r
+ </storageModule>\r
+ <storageModule moduleId="cdtBuildSystem" version="4.0.0">\r
+ <configuration artifactName="${ProjName}" buildArtefactType="org.eclipse.cdt.build.core.buildArtefactType.exe" buildProperties="org.eclipse.cdt.build.core.buildArtefactType=org.eclipse.cdt.build.core.buildArtefactType.exe,org.eclipse.cdt.build.core.buildType=org.eclipse.cdt.build.core.buildType.debug" cleanCommand="${cross_rm} -rf" description="" errorParsers="org.eclipse.cdt.core.GASErrorParser;org.eclipse.cdt.core.GmakeErrorParser;org.eclipse.cdt.core.GLDErrorParser;org.eclipse.cdt.core.CWDLocator;org.eclipse.cdt.core.GCCErrorParser" id="ilg.gnumcueclipse.managedbuild.cross.riscv.config.elf.debug.2049051127" name="Debug" parent="ilg.gnumcueclipse.managedbuild.cross.riscv.config.elf.debug" postannouncebuildStep="" postbuildStep="" preannouncebuildStep="" prebuildStep="">\r
+ <folderInfo id="ilg.gnumcueclipse.managedbuild.cross.riscv.config.elf.debug.2049051127." name="/" resourcePath="">\r
+ <toolChain errorParsers="" id="ilg.gnumcueclipse.managedbuild.cross.riscv.toolchain.elf.debug.1135421195" name="RISC-V Cross GCC" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.toolchain.elf.debug">\r
+ <option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.addtools.createflash.1236561658" name="Create flash image" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.addtools.createflash" useByScannerDiscovery="false" value="true" valueType="boolean"/>\r
+ <option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.addtools.createlisting.197330232" name="Create extended listing" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.addtools.createlisting" useByScannerDiscovery="false" value="true" valueType="boolean"/>\r
+ <option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.addtools.printsize.306588546" name="Print size" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.addtools.printsize" useByScannerDiscovery="false" value="true" valueType="boolean"/>\r
+ <option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.optimization.level.1940053873" name="Optimization Level" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.optimization.level" useByScannerDiscovery="true" value="ilg.gnumcueclipse.managedbuild.cross.riscv.option.optimization.level.none" valueType="enumerated"/>\r
+ <option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.optimization.messagelength.565243439" name="Message length (-fmessage-length=0)" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.optimization.messagelength" useByScannerDiscovery="true" value="true" valueType="boolean"/>\r
+ <option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.optimization.signedchar.321222073" name="'char' is signed (-fsigned-char)" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.optimization.signedchar" useByScannerDiscovery="true" value="true" valueType="boolean"/>\r
+ <option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.optimization.functionsections.1177210712" name="Function sections (-ffunction-sections)" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.optimization.functionsections" useByScannerDiscovery="true" value="true" valueType="boolean"/>\r
+ <option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.optimization.datasections.1159308156" name="Data sections (-fdata-sections)" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.optimization.datasections" useByScannerDiscovery="true" value="true" valueType="boolean"/>\r
+ <option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.debugging.level.400131419" name="Debug level" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.debugging.level" useByScannerDiscovery="true" value="ilg.gnumcueclipse.managedbuild.cross.riscv.option.debugging.level.max" valueType="enumerated"/>\r
+ <option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.debugging.format.227460743" name="Debug format" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.debugging.format" useByScannerDiscovery="true"/>\r
+ <option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.toolchain.name.39106845" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.toolchain.name" useByScannerDiscovery="false" value="RISC-V GCC/Newlib" valueType="string"/>\r
+ <option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.command.prefix.975904647" name="Prefix" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.command.prefix" useByScannerDiscovery="false" value="riscv64-unknown-elf-" valueType="string"/>\r
+ <option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.command.c.629106139" name="C compiler" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.command.c" useByScannerDiscovery="false" value="gcc" valueType="string"/>\r
+ <option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.command.cpp.700052137" name="C++ compiler" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.command.cpp" useByScannerDiscovery="false" value="g++" valueType="string"/>\r
+ <option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.command.ar.1315168450" name="Archiver" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.command.ar" useByScannerDiscovery="false" value="ar" valueType="string"/>\r
+ <option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.command.objcopy.729800518" name="Hex/Bin converter" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.command.objcopy" useByScannerDiscovery="false" value="objcopy" valueType="string"/>\r
+ <option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.command.objdump.1799678707" name="Listing generator" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.command.objdump" useByScannerDiscovery="false" value="objdump" valueType="string"/>\r
+ <option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.command.size.2116391716" name="Size command" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.command.size" useByScannerDiscovery="false" value="size" valueType="string"/>\r
+ <option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.command.make.323254382" name="Build command" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.command.make" useByScannerDiscovery="false" value="make" valueType="string"/>\r
+ <option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.command.rm.1360582657" name="Remove command" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.command.rm" useByScannerDiscovery="false" value="rm" valueType="string"/>\r
+ <option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.target.isa.base.1725087349" name="Architecture" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.target.isa.base" useByScannerDiscovery="false" value="ilg.gnumcueclipse.managedbuild.cross.riscv.option.target.arch.rv32i" valueType="enumerated"/>\r
+ <option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.target.isa.multiply.1573871360" name="Multiply extension (RVM)" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.target.isa.multiply" useByScannerDiscovery="false" value="true" valueType="boolean"/>\r
+ <option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.target.abi.integer.957415439" name="Integer ABI" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.target.abi.integer" useByScannerDiscovery="false" value="ilg.gnumcueclipse.managedbuild.cross.riscv.option.abi.integer.ilp32" valueType="enumerated"/>\r
+ <targetPlatform archList="all" binaryParser="org.eclipse.cdt.core.ELF" id="ilg.gnumcueclipse.managedbuild.cross.riscv.targetPlatform.1851994667" isAbstract="false" osList="all" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.targetPlatform"/>\r
+ <builder buildPath="${workspace_loc:/miv-rv32im-freertos-port-test}/Debug" errorParsers="org.eclipse.cdt.core.GmakeErrorParser;org.eclipse.cdt.core.CWDLocator" id="ilg.gnumcueclipse.managedbuild.cross.riscv.builder.1748717066" keepEnvironmentInBuildfile="false" managedBuildOn="true" name="Gnu Make Builder" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.builder"/>\r
+ <tool command="${cross_prefix}${cross_c}${cross_suffix}" commandLinePattern="${COMMAND} ${cross_toolchain_flags} ${FLAGS} -c ${OUTPUT_FLAG} ${OUTPUT_PREFIX}${OUTPUT} ${INPUTS}" errorParsers="org.eclipse.cdt.core.GASErrorParser;org.eclipse.cdt.core.GCCErrorParser" id="ilg.gnumcueclipse.managedbuild.cross.riscv.tool.assembler.1205277158" name="GNU RISC-V Cross Assembler" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.tool.assembler">\r
+ <option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.assembler.usepreprocessor.1853992692" name="Use preprocessor" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.assembler.usepreprocessor" useByScannerDiscovery="false" value="true" valueType="boolean"/>\r
+ <inputType id="ilg.gnumcueclipse.managedbuild.cross.riscv.tool.assembler.input.1786331150" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.tool.assembler.input"/>\r
+ </tool>\r
+ <tool command="${cross_prefix}${cross_c}${cross_suffix}" commandLinePattern="${COMMAND} ${cross_toolchain_flags} ${FLAGS} -c ${OUTPUT_FLAG} ${OUTPUT_PREFIX}${OUTPUT} ${INPUTS}" errorParsers="org.eclipse.cdt.core.GLDErrorParser;org.eclipse.cdt.core.GCCErrorParser" id="ilg.gnumcueclipse.managedbuild.cross.riscv.tool.c.compiler.894708922" name="GNU RISC-V Cross C Compiler" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.tool.c.compiler">\r
+ <option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.c.compiler.include.paths.1818715770" name="Include paths (-I)" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.c.compiler.include.paths" useByScannerDiscovery="true" valueType="includePath">\r
+ <listOptionValue builtIn="false" value=""${workspace_loc:/${ProjName}/FreeRTOS_Source/include}""/>\r
+ <listOptionValue builtIn="false" value=""${workspace_loc:/${ProjName}/FreeRTOS_Source/portable/ThirdParty/GCC/RISC-V}""/>\r
+ <listOptionValue builtIn="false" value=""${workspace_loc:/${ProjName}}""/>\r
+ <listOptionValue builtIn="false" value=""${workspace_loc:/${ProjName}/drivers/CoreGPIO}""/>\r
+ <listOptionValue builtIn="false" value=""${workspace_loc:/${ProjName}/drivers/Core16550}""/>\r
+ <listOptionValue builtIn="false" value=""${workspace_loc:/${ProjName}/drivers/CoreUARTapb}""/>\r
+ <listOptionValue builtIn="false" value=""${workspace_loc:/${ProjName}/drivers/CoreTimer}""/>\r
+ <listOptionValue builtIn="false" value=""${workspace_loc:/${ProjName}/drivers/CoreSPI}""/>\r
+ <listOptionValue builtIn="false" value=""${workspace_loc:/${ProjName}/hal}""/>\r
+ <listOptionValue builtIn="false" value=""${workspace_loc:/${ProjName}/riscv_hal}""/>\r
+ </option>\r
+ <option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.c.compiler.defs.43291576" name="Defined symbols (-D)" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.c.compiler.defs" useByScannerDiscovery="true" valueType="definedSymbols">\r
+ <listOptionValue builtIn="false" value="MSCC_STDIO_THRU_CORE_UART_APB"/>\r
+ </option>\r
+ <inputType id="ilg.gnumcueclipse.managedbuild.cross.riscv.tool.c.compiler.input.1901773760" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.tool.c.compiler.input"/>\r
+ </tool>\r
+ <tool id="ilg.gnumcueclipse.managedbuild.cross.riscv.tool.cpp.compiler.1713474071" name="GNU RISC-V Cross C++ Compiler" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.tool.cpp.compiler"/>\r
+ <tool command="${cross_prefix}${cross_c}${cross_suffix}" commandLinePattern="${COMMAND} ${cross_toolchain_flags} ${FLAGS} ${OUTPUT_FLAG} ${OUTPUT_PREFIX}${OUTPUT} ${INPUTS}" errorParsers="" id="ilg.gnumcueclipse.managedbuild.cross.riscv.tool.c.linker.209069143" name="GNU RISC-V Cross C Linker" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.tool.c.linker">\r
+ <option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.c.linker.gcsections.991946343" name="Remove unused sections (-Xlinker --gc-sections)" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.c.linker.gcsections" useByScannerDiscovery="false" value="true" valueType="boolean"/>\r
+ <option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.c.linker.scriptfile.746597241" name="Script files (-T)" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.c.linker.scriptfile" useByScannerDiscovery="false" valueType="stringList">\r
+ <listOptionValue builtIn="false" value=""${workspace_loc:/${ProjName}/riscv_hal/microsemi-riscv-ram.ld}""/>\r
+ </option>\r
+ <option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.c.linker.nostart.1750314954" name="Do not use standard start files (-nostartfiles)" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.c.linker.nostart" useByScannerDiscovery="false" value="true" valueType="boolean"/>\r
+ <option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.c.linker.usenewlibnano.991677097" name="Use newlib-nano (--specs=nano.specs)" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.c.linker.usenewlibnano" useByScannerDiscovery="false" value="true" valueType="boolean"/>\r
+ <inputType id="ilg.gnumcueclipse.managedbuild.cross.riscv.tool.c.linker.input.314001493" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.tool.c.linker.input">\r
+ <additionalInput kind="additionalinputdependency" paths="$(USER_OBJS)"/>\r
+ <additionalInput kind="additionalinput" paths="$(LIBS)"/>\r
+ </inputType>\r
+ </tool>\r
+ <tool id="ilg.gnumcueclipse.managedbuild.cross.riscv.tool.cpp.linker.1999185643" name="GNU RISC-V Cross C++ Linker" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.tool.cpp.linker">\r
+ <option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.cpp.linker.gcsections.1490980679" name="Remove unused sections (-Xlinker --gc-sections)" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.cpp.linker.gcsections" value="true" valueType="boolean"/>\r
+ <option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.cpp.linker.scriptfile.1026577013" name="Script files (-T)" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.cpp.linker.scriptfile" valueType="stringList">\r
+ <listOptionValue builtIn="false" value=""${workspace_loc:/${ProjName}/riscv_hal/microsemi-riscv-ram.ld}""/>\r
+ </option>\r
+ <option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.cpp.linker.nostart.1240127315" name="Do not use standard start files (-nostartfiles)" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.cpp.linker.nostart" value="true" valueType="boolean"/>\r
+ <option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.cpp.linker.usenewlibnano.89628615" name="Use newlib-nano (--specs=nano.specs)" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.cpp.linker.usenewlibnano" value="true" valueType="boolean"/>\r
+ </tool>\r
+ <tool id="ilg.gnumcueclipse.managedbuild.cross.riscv.tool.archiver.690189418" name="GNU RISC-V Cross Archiver" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.tool.archiver"/>\r
+ <tool command="${cross_prefix}${cross_objcopy}${cross_suffix}" commandLinePattern="${COMMAND} ${FLAGS} ${OUTPUT_FLAG} ${OUTPUT_PREFIX}${OUTPUT}" errorParsers="" id="ilg.gnumcueclipse.managedbuild.cross.riscv.tool.createflash.1183225084" name="GNU RISC-V Cross Create Flash Image" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.tool.createflash"/>\r
+ <tool command="${cross_prefix}${cross_objdump}${cross_suffix}" commandLinePattern="${COMMAND} ${FLAGS} ${OUTPUT_FLAG} ${OUTPUT_PREFIX}${OUTPUT}" errorParsers="" id="ilg.gnumcueclipse.managedbuild.cross.riscv.tool.createlisting.876462403" name="GNU RISC-V Cross Create Listing" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.tool.createlisting">\r
+ <option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.createlisting.source.1650627599" name="Display source (--source|-S)" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.createlisting.source" useByScannerDiscovery="false" value="true" valueType="boolean"/>\r
+ <option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.createlisting.allheaders.1290189840" name="Display all headers (--all-headers|-x)" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.createlisting.allheaders" useByScannerDiscovery="false" value="true" valueType="boolean"/>\r
+ <option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.createlisting.demangle.1153388295" name="Demangle names (--demangle|-C)" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.createlisting.demangle" useByScannerDiscovery="false" value="true" valueType="boolean"/>\r
+ <option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.createlisting.linenumbers.59828896" name="Display line numbers (--line-numbers|-l)" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.createlisting.linenumbers" useByScannerDiscovery="false" value="true" valueType="boolean"/>\r
+ <option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.createlisting.wide.2003727408" name="Wide lines (--wide|-w)" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.createlisting.wide" useByScannerDiscovery="false" value="true" valueType="boolean"/>\r
+ </tool>\r
+ <tool command="${cross_prefix}${cross_size}${cross_suffix}" commandLinePattern="${COMMAND} ${FLAGS}" errorParsers="" id="ilg.gnumcueclipse.managedbuild.cross.riscv.tool.printsize.1868273119" name="GNU RISC-V Cross Print Size" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.tool.printsize">\r
+ <option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.printsize.format.1198877735" name="Size format" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.printsize.format" useByScannerDiscovery="false"/>\r
+ </tool>\r
+ </toolChain>\r
+ </folderInfo>\r
+ <sourceEntries>\r
+ <entry excluding="FreeRTOS/portable/MemMang/heap_5.c|FreeRTOS/portable/MemMang/heap_4.c|FreeRTOS/portable/MemMang/heap_3.c|FreeRTOS/portable/MemMang/heap_1.c" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name=""/>\r
+ </sourceEntries>\r
+ </configuration>\r
+ </storageModule>\r
+ <storageModule moduleId="org.eclipse.cdt.core.externalSettings"/>\r
+ </cconfiguration>\r
+ </storageModule>\r
+ <storageModule moduleId="cdtBuildSystem" version="4.0.0">\r
+ <project id="miv-rv32im-freertos-port-test.ilg.gnumcueclipse.managedbuild.cross.riscv.target.elf.1563732131" name="Executable" projectType="ilg.gnumcueclipse.managedbuild.cross.riscv.target.elf"/>\r
+ </storageModule>\r
+ <storageModule moduleId="scannerConfiguration">\r
+ <autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>\r
+ <scannerConfigBuildInfo instanceId="ilg.gnumcueclipse.managedbuild.cross.riscv.config.elf.release.1785100359;ilg.gnumcueclipse.managedbuild.cross.riscv.config.elf.release.1785100359.;ilg.gnumcueclipse.managedbuild.cross.riscv.tool.c.compiler.1642196096;ilg.gnumcueclipse.managedbuild.cross.riscv.tool.c.compiler.input.702511061">\r
+ <autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>\r
+ </scannerConfigBuildInfo>\r
+ <scannerConfigBuildInfo instanceId="ilg.gnumcueclipse.managedbuild.cross.riscv.config.elf.debug.2049051127;ilg.gnumcueclipse.managedbuild.cross.riscv.config.elf.debug.2049051127.;ilg.gnumcueclipse.managedbuild.cross.riscv.tool.c.compiler.894708922;ilg.gnumcueclipse.managedbuild.cross.riscv.tool.c.compiler.input.1901773760">\r
+ <autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>\r
+ </scannerConfigBuildInfo>\r
+ </storageModule>\r
+ <storageModule moduleId="org.eclipse.cdt.core.LanguageSettingsProviders"/>\r
+ <storageModule moduleId="org.eclipse.cdt.make.core.buildtargets"/>\r
+ <storageModule moduleId="refreshScope"/>\r
+</cproject>\r
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>\r
+<projectDescription>\r
+ <name>RTOSDemo</name>\r
+ <comment></comment>\r
+ <projects>\r
+ </projects>\r
+ <buildSpec>\r
+ <buildCommand>\r
+ <name>org.eclipse.cdt.managedbuilder.core.genmakebuilder</name>\r
+ <triggers>clean,full,incremental,</triggers>\r
+ <arguments>\r
+ </arguments>\r
+ </buildCommand>\r
+ <buildCommand>\r
+ <name>org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder</name>\r
+ <triggers>full,incremental,</triggers>\r
+ <arguments>\r
+ </arguments>\r
+ </buildCommand>\r
+ </buildSpec>\r
+ <natures>\r
+ <nature>org.eclipse.cdt.core.cnature</nature>\r
+ <nature>org.eclipse.cdt.managedbuilder.core.managedBuildNature</nature>\r
+ <nature>org.eclipse.cdt.managedbuilder.core.ScannerConfigNature</nature>\r
+ </natures>\r
+ <linkedResources>\r
+ <link>\r
+ <name>FreeRTOS_Source</name>\r
+ <type>2</type>\r
+ <locationURI>FREERTOS_ROOT/FreeRTOS/Source</locationURI>\r
+ </link>\r
+ </linkedResources>\r
+ <filteredResources>\r
+ <filter>\r
+ <id>1529524430510</id>\r
+ <name>FreeRTOS_Source</name>\r
+ <type>9</type>\r
+ <matcher>\r
+ <id>org.eclipse.ui.ide.multiFilter</id>\r
+ <arguments>1.0-name-matches-false-false-include</arguments>\r
+ </matcher>\r
+ </filter>\r
+ <filter>\r
+ <id>1529524430514</id>\r
+ <name>FreeRTOS_Source</name>\r
+ <type>9</type>\r
+ <matcher>\r
+ <id>org.eclipse.ui.ide.multiFilter</id>\r
+ <arguments>1.0-name-matches-false-false-portable</arguments>\r
+ </matcher>\r
+ </filter>\r
+ <filter>\r
+ <id>1529524430518</id>\r
+ <name>FreeRTOS_Source</name>\r
+ <type>5</type>\r
+ <matcher>\r
+ <id>org.eclipse.ui.ide.multiFilter</id>\r
+ <arguments>1.0-name-matches-false-false-event_groups.c</arguments>\r
+ </matcher>\r
+ </filter>\r
+ <filter>\r
+ <id>1529524430521</id>\r
+ <name>FreeRTOS_Source</name>\r
+ <type>5</type>\r
+ <matcher>\r
+ <id>org.eclipse.ui.ide.multiFilter</id>\r
+ <arguments>1.0-name-matches-false-false-list.c</arguments>\r
+ </matcher>\r
+ </filter>\r
+ <filter>\r
+ <id>1529524430525</id>\r
+ <name>FreeRTOS_Source</name>\r
+ <type>5</type>\r
+ <matcher>\r
+ <id>org.eclipse.ui.ide.multiFilter</id>\r
+ <arguments>1.0-name-matches-false-false-queue.c</arguments>\r
+ </matcher>\r
+ </filter>\r
+ <filter>\r
+ <id>1529524430529</id>\r
+ <name>FreeRTOS_Source</name>\r
+ <type>5</type>\r
+ <matcher>\r
+ <id>org.eclipse.ui.ide.multiFilter</id>\r
+ <arguments>1.0-name-matches-false-false-stream_buffer.c</arguments>\r
+ </matcher>\r
+ </filter>\r
+ <filter>\r
+ <id>1529524430533</id>\r
+ <name>FreeRTOS_Source</name>\r
+ <type>5</type>\r
+ <matcher>\r
+ <id>org.eclipse.ui.ide.multiFilter</id>\r
+ <arguments>1.0-name-matches-false-false-tasks.c</arguments>\r
+ </matcher>\r
+ </filter>\r
+ <filter>\r
+ <id>1529524430538</id>\r
+ <name>FreeRTOS_Source</name>\r
+ <type>5</type>\r
+ <matcher>\r
+ <id>org.eclipse.ui.ide.multiFilter</id>\r
+ <arguments>1.0-name-matches-false-false-timers.c</arguments>\r
+ </matcher>\r
+ </filter>\r
+ <filter>\r
+ <id>1529524475525</id>\r
+ <name>FreeRTOS_Source/portable</name>\r
+ <type>9</type>\r
+ <matcher>\r
+ <id>org.eclipse.ui.ide.multiFilter</id>\r
+ <arguments>1.0-name-matches-false-false-ThirdParty</arguments>\r
+ </matcher>\r
+ </filter>\r
+ <filter>\r
+ <id>1529524475530</id>\r
+ <name>FreeRTOS_Source/portable</name>\r
+ <type>9</type>\r
+ <matcher>\r
+ <id>org.eclipse.ui.ide.multiFilter</id>\r
+ <arguments>1.0-name-matches-false-false-MemMang</arguments>\r
+ </matcher>\r
+ </filter>\r
+ <filter>\r
+ <id>1529524494421</id>\r
+ <name>FreeRTOS_Source/portable/MemMang</name>\r
+ <type>5</type>\r
+ <matcher>\r
+ <id>org.eclipse.ui.ide.multiFilter</id>\r
+ <arguments>1.0-name-matches-false-false-heap_4.c</arguments>\r
+ </matcher>\r
+ </filter>\r
+ <filter>\r
+ <id>1529524515837</id>\r
+ <name>FreeRTOS_Source/portable/ThirdParty</name>\r
+ <type>9</type>\r
+ <matcher>\r
+ <id>org.eclipse.ui.ide.multiFilter</id>\r
+ <arguments>1.0-name-matches-false-false-GCC</arguments>\r
+ </matcher>\r
+ </filter>\r
+ <filter>\r
+ <id>1529524627661</id>\r
+ <name>FreeRTOS_Source/portable/ThirdParty/GCC</name>\r
+ <type>9</type>\r
+ <matcher>\r
+ <id>org.eclipse.ui.ide.multiFilter</id>\r
+ <arguments>1.0-name-matches-false-false-RISC-V</arguments>\r
+ </matcher>\r
+ </filter>\r
+ </filteredResources>\r
+ <variableList>\r
+ <variable>\r
+ <name>FREERTOS_ROOT</name>\r
+ <value>$%7BPARENT-3-PROJECT_LOC%7D</value>\r
+ </variable>\r
+ <variable>\r
+ <name>copy_PARENT</name>\r
+ <value>$%7BPARENT-4-PROJECT_LOC%7D/FreeRTOS/WorkingCopy/FreeRTOS</value>\r
+ </variable>\r
+ </variableList>\r
+</projectDescription>\r
--- /dev/null
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>\r
+<project>\r
+ <configuration id="ilg.gnumcueclipse.managedbuild.cross.riscv.config.elf.debug.2049051127" name="Debug">\r
+ <extension point="org.eclipse.cdt.core.LanguageSettingsProvider">\r
+ <provider copy-of="extension" id="org.eclipse.cdt.ui.UserLanguageSettingsProvider"/>\r
+ <provider-reference id="org.eclipse.cdt.core.ReferencedProjectsLanguageSettingsProvider" ref="shared-provider"/>\r
+ <provider-reference id="org.eclipse.cdt.managedbuilder.core.MBSLanguageSettingsProvider" ref="shared-provider"/>\r
+ <provider class="org.eclipse.cdt.managedbuilder.language.settings.providers.GCCBuiltinSpecsDetector" console="false" env-hash="886405286544253612" id="ilg.gnumcueclipse.managedbuild.cross.riscv.GCCBuiltinSpecsDetector" keep-relative-paths="false" name="CDT RISC-V Cross GCC Built-in Compiler Settings" parameter="${COMMAND} ${FLAGS} ${cross_toolchain_flags} -E -P -v -dD "${INPUTS}"" prefer-non-shared="true">\r
+ <language-scope id="org.eclipse.cdt.core.gcc"/>\r
+ <language-scope id="org.eclipse.cdt.core.g++"/>\r
+ </provider>\r
+ </extension>\r
+ </configuration>\r
+</project>\r
--- /dev/null
+/*\r
+ FreeRTOS V8.2.3 - Copyright (C) 2015 Real Time Engineers Ltd.\r
+ All rights reserved\r
+\r
+ VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.\r
+\r
+ This file is part of the FreeRTOS distribution.\r
+\r
+ FreeRTOS is free software; you can redistribute it and/or modify it under\r
+ the terms of the GNU General Public License (version 2) as published by the\r
+ Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception.\r
+\r
+ ***************************************************************************\r
+ >>! NOTE: The modification to the GPL is included to allow you to !<<\r
+ >>! distribute a combined work that includes FreeRTOS without being !<<\r
+ >>! obliged to provide the source code for proprietary components !<<\r
+ >>! outside of the FreeRTOS kernel. !<<\r
+ ***************************************************************************\r
+\r
+ FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY\r
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS\r
+ FOR A PARTICULAR PURPOSE. Full license text is available on the following\r
+ link: http://www.freertos.org/a00114.html\r
+\r
+ ***************************************************************************\r
+ * *\r
+ * FreeRTOS provides completely free yet professionally developed, *\r
+ * robust, strictly quality controlled, supported, and cross *\r
+ * platform software that is more than just the market leader, it *\r
+ * is the industry's de facto standard. *\r
+ * *\r
+ * Help yourself get started quickly while simultaneously helping *\r
+ * to support the FreeRTOS project by purchasing a FreeRTOS *\r
+ * tutorial book, reference manual, or both: *\r
+ * http://www.FreeRTOS.org/Documentation *\r
+ * *\r
+ ***************************************************************************\r
+\r
+ http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading\r
+ the FAQ page "My application does not run, what could be wrong?". Have you\r
+ defined configASSERT()?\r
+\r
+ http://www.FreeRTOS.org/support - In return for receiving this top quality\r
+ embedded software for free we request you assist our global community by\r
+ participating in the support forum.\r
+\r
+ http://www.FreeRTOS.org/training - Investing in training allows your team to\r
+ be as productive as possible as early as possible. Now you can receive\r
+ FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers\r
+ Ltd, and the world's leading authority on the world's leading RTOS.\r
+\r
+ http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,\r
+ including FreeRTOS+Trace - an indispensable productivity tool, a DOS\r
+ compatible FAT file system, and our tiny thread aware UDP/IP stack.\r
+\r
+ http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate.\r
+ Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS.\r
+\r
+ http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High\r
+ Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS\r
+ licenses offer ticketed support, indemnification and commercial middleware.\r
+\r
+ http://www.SafeRTOS.com - High Integrity Systems also provide a safety\r
+ engineered and independently SIL3 certified version for use in safety and\r
+ mission critical applications that require provable dependability.\r
+\r
+ 1 tab == 4 spaces!\r
+*/\r
+\r
+\r
+#ifndef FREERTOS_CONFIG_H\r
+#define FREERTOS_CONFIG_H\r
+\r
+\r
+/*-----------------------------------------------------------\r
+ * Application specific definitions.\r
+ *\r
+ * These definitions should be adjusted for your particular hardware and\r
+ * application requirements.\r
+ *\r
+ * THESE PARAMETERS ARE DESCRIBED WITHIN THE 'CONFIGURATION' SECTION OF THE\r
+ * FreeRTOS API DOCUMENTATION AVAILABLE ON THE FreeRTOS.org WEB SITE.\r
+ *\r
+ * See http://www.freertos.org/a00110.html.\r
+ *----------------------------------------------------------*/\r
+\r
+#include <stdint.h>\r
+#include <string.h>\r
+#include "riscv_plic.h"\r
+\r
+extern uint32_t SystemCoreClock;\r
+\r
+#define configUSE_PREEMPTION 1\r
+#define configUSE_IDLE_HOOK 1\r
+#define configUSE_TICK_HOOK 0\r
+#define configCPU_CLOCK_HZ ( ( unsigned long ) 83000000 )\r
+#define configTICK_RATE_HZ ( ( TickType_t ) 1000 )\r
+#define configMAX_PRIORITIES ( 5 )\r
+#define configMINIMAL_STACK_SIZE ( ( unsigned short ) 1024 )\r
+#define configTOTAL_HEAP_SIZE ( ( size_t ) ( 100 * 1024 ) )\r
+#define configMAX_TASK_NAME_LEN ( 16 )\r
+#define configUSE_TRACE_FACILITY 1\r
+#define configUSE_16_BIT_TICKS 0\r
+#define configIDLE_SHOULD_YIELD 1\r
+#define configUSE_MUTEXES 1\r
+#define configQUEUE_REGISTRY_SIZE 8\r
+#define configCHECK_FOR_STACK_OVERFLOW 0 //2\r
+#define configUSE_RECURSIVE_MUTEXES 1\r
+#define configUSE_MALLOC_FAILED_HOOK 1\r
+#define configUSE_APPLICATION_TASK_TAG 0\r
+#define configUSE_COUNTING_SEMAPHORES 1\r
+#define configGENERATE_RUN_TIME_STATS 0\r
+\r
+/* Co-routine definitions. */\r
+#define configUSE_CO_ROUTINES 0\r
+#define configMAX_CO_ROUTINE_PRIORITIES ( 2 )\r
+\r
+/* Software timer definitions. */\r
+#define configUSE_TIMERS 0\r
+#define configTIMER_TASK_PRIORITY ( 2 )\r
+#define configTIMER_QUEUE_LENGTH 2\r
+#define configTIMER_TASK_STACK_DEPTH ( configMINIMAL_STACK_SIZE )\r
+\r
+/* Task priorities. Allow these to be overridden. */\r
+#ifndef uartPRIMARY_PRIORITY\r
+ #define uartPRIMARY_PRIORITY ( configMAX_PRIORITIES - 3 )\r
+#endif\r
+\r
+/* Set the following definitions to 1 to include the API function, or zero\r
+to exclude the API function. */\r
+#define INCLUDE_vTaskPrioritySet 1\r
+#define INCLUDE_uxTaskPriorityGet 1\r
+#define INCLUDE_vTaskDelete 1\r
+#define INCLUDE_vTaskCleanUpResources 1\r
+#define INCLUDE_vTaskSuspend 1\r
+#define INCLUDE_vTaskDelayUntil 1\r
+#define INCLUDE_vTaskDelay 1\r
+#define INCLUDE_eTaskGetState 1\r
+\r
+/* Normal assert() semantics without relying on the provision of an assert.h\r
+header file. */\r
+#define configASSERT( x ) if( ( x ) == 0 ) { taskDISABLE_INTERRUPTS(); for( ;; ); }\r
+\r
+/* Definitions that map the FreeRTOS port interrupt handlers to their CMSIS\r
+standard names - or at least those used in the unmodified vector table. */\r
+#define vPortSVCHandler SVCall_Handler\r
+#define xPortPendSVHandler PendSV_Handler\r
+#define vPortSysTickHandler SysTick_Handler\r
+\r
+extern void vApplicationMallocFailedHook();\r
+#endif /* FREERTOS_CONFIG_H */\r
--- /dev/null
+## FreeRTOS port for Mi-V Soft Processor\r
+\r
+### HW Platform and FPGA design:\r
+This project is tested on following hardware platforms:\r
+\r
+RISCV-Creative-Board\r
+- [RISC-V Creative board Mi-V Sample Design](https://github.com/RISCV-on-Microsemi-FPGA/RISC-V-Creative-Board/tree/master/Programming_The_Target_Device/PROC_SUBSYSTEM_MIV_RV32IMA_BaseDesign)\r
+\r
+PolarFire-Eval-Kit\r
+- [PolarFire Eval Kit RISC-V Sample Design](https://github.com/RISCV-on-Microsemi-FPGA/PolarFire-Eval-Kit/tree/master/Programming_The_Target_Device/MIV_RV32IMA_L1_AHB_BaseDesign)\r
+\r
+SmartFusion2-Advanced-Dev-Kit\r
+- [SmartFusion2 Advanced Development Kit RISC-V Sample Design](https://github.com/RISCV-on-Microsemi-FPGA/SmartFusion2-Advanced-Dev-Kit/tree/master/Programming_The_Target_Device/PROC_SUBSYSTEM_BaseDesign)\r
+\r
+### How to run the FreeRTOS RISC-V port:\r
+To know how to use the SoftConsole workspace, please refer the [Readme.md](https://github.com/RISCV-on-Microsemi-FPGA/SoftConsole/blob/master/README.md)\r
+\r
+The miv-rv32im-freertos-port-test is a self contained project. This project demonstrates \r
+the FreeRTOS running with Microsemi RISC-V processor. This project creates two \r
+tasks and runs them at regular intervals.\r
+ \r
+This example project requires USB-UART interface to be connected to a host PC. \r
+The host PC must connect to the serial port using a terminal emulator such as \r
+TeraTerm or PuTTY configured as follows:\r
+ \r
+ - 115200 baud\r
+ - 8 data bits\r
+ - 1 stop bit\r
+ - no parity\r
+ - no flow control\r
+ \r
+The ./hw_platform.h file contains the design related information that is required \r
+for this project. If you update the design, the hw_platform.h must be updated \r
+accordingly.\r
+\r
+### FreeRTOS Configurations\r
+You must configure the FreeRTOS as per your applications need. Please read and modify FreeRTOSConfig.h.\r
+E.g. You must set configCPU_CLOCK_HZ parameter in FreeRTOSConfig.h according to the hardware platform \r
+design that you are using. \r
+\r
+The RISC-V creative board design uses 66Mhz processor clock. The PolarFire Eval Kit design uses 50Mhz processor clock. The SmartFusion2 Adv. Development kit design uses 83Mhz processor clock.\r
+\r
+### Microsemi SoftConsole Toolchain\r
+To know more please refer: [SoftConsole](https://github.com/RISCV-on-Microsemi-FPGA/SoftConsole)\r
+\r
+### Documentation for Microsemi RISC-V processor, SoftConsole toochain, Debug Tools, FPGA design etc.\r
+To know more please refer: [Documentation](https://github.com/RISCV-on-Microsemi-FPGA/Documentation)\r
+ \r
--- /dev/null
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>\r
+<launchConfiguration type="ilg.gnumcueclipse.debug.gdbjtag.openocd.launchConfigurationType">\r
+<booleanAttribute key="ilg.gnumcueclipse.debug.gdbjtag.openocd.doContinue" value="true"/>\r
+<booleanAttribute key="ilg.gnumcueclipse.debug.gdbjtag.openocd.doDebugInRam" value="false"/>\r
+<booleanAttribute key="ilg.gnumcueclipse.debug.gdbjtag.openocd.doFirstReset" value="true"/>\r
+<booleanAttribute key="ilg.gnumcueclipse.debug.gdbjtag.openocd.doGdbServerAllocateConsole" value="true"/>\r
+<booleanAttribute key="ilg.gnumcueclipse.debug.gdbjtag.openocd.doGdbServerAllocateTelnetConsole" value="false"/>\r
+<booleanAttribute key="ilg.gnumcueclipse.debug.gdbjtag.openocd.doSecondReset" value="false"/>\r
+<booleanAttribute key="ilg.gnumcueclipse.debug.gdbjtag.openocd.doStartGdbServer" value="true"/>\r
+<booleanAttribute key="ilg.gnumcueclipse.debug.gdbjtag.openocd.enableSemihosting" value="false"/>\r
+<stringAttribute key="ilg.gnumcueclipse.debug.gdbjtag.openocd.firstResetType" value="init"/>\r
+<stringAttribute key="ilg.gnumcueclipse.debug.gdbjtag.openocd.gdbClientOtherCommands" value="set mem inaccessible-by-default off set arch riscv:rv32"/>\r
+<stringAttribute key="ilg.gnumcueclipse.debug.gdbjtag.openocd.gdbClientOtherOptions" value=""/>\r
+<stringAttribute key="ilg.gnumcueclipse.debug.gdbjtag.openocd.gdbServerConnectionAddress" value=""/>\r
+<stringAttribute key="ilg.gnumcueclipse.debug.gdbjtag.openocd.gdbServerExecutable" value="${openocd_path}/${openocd_executable}"/>\r
+<intAttribute key="ilg.gnumcueclipse.debug.gdbjtag.openocd.gdbServerGdbPortNumber" value="3333"/>\r
+<stringAttribute key="ilg.gnumcueclipse.debug.gdbjtag.openocd.gdbServerLog" value=""/>\r
+<stringAttribute key="ilg.gnumcueclipse.debug.gdbjtag.openocd.gdbServerOther" value="--file board/microsemi-riscv.cfg"/>\r
+<intAttribute key="ilg.gnumcueclipse.debug.gdbjtag.openocd.gdbServerTelnetPortNumber" value="4444"/>\r
+<stringAttribute key="ilg.gnumcueclipse.debug.gdbjtag.openocd.otherInitCommands" value=""/>\r
+<stringAttribute key="ilg.gnumcueclipse.debug.gdbjtag.openocd.otherRunCommands" value=""/>\r
+<stringAttribute key="ilg.gnumcueclipse.debug.gdbjtag.openocd.secondResetType" value="halt"/>\r
+<stringAttribute key="org.eclipse.cdt.debug.gdbjtag.core.imageFileName" value=""/>\r
+<stringAttribute key="org.eclipse.cdt.debug.gdbjtag.core.imageOffset" value=""/>\r
+<stringAttribute key="org.eclipse.cdt.debug.gdbjtag.core.ipAddress" value="localhost"/>\r
+<stringAttribute key="org.eclipse.cdt.debug.gdbjtag.core.jtagDevice" value="GNU MCU OpenOCD"/>\r
+<booleanAttribute key="org.eclipse.cdt.debug.gdbjtag.core.loadImage" value="true"/>\r
+<booleanAttribute key="org.eclipse.cdt.debug.gdbjtag.core.loadSymbols" value="true"/>\r
+<stringAttribute key="org.eclipse.cdt.debug.gdbjtag.core.pcRegister" value=""/>\r
+<intAttribute key="org.eclipse.cdt.debug.gdbjtag.core.portNumber" value="3333"/>\r
+<booleanAttribute key="org.eclipse.cdt.debug.gdbjtag.core.setPcRegister" value="false"/>\r
+<booleanAttribute key="org.eclipse.cdt.debug.gdbjtag.core.setResume" value="false"/>\r
+<booleanAttribute key="org.eclipse.cdt.debug.gdbjtag.core.setStopAt" value="true"/>\r
+<stringAttribute key="org.eclipse.cdt.debug.gdbjtag.core.stopAt" value="main"/>\r
+<stringAttribute key="org.eclipse.cdt.debug.gdbjtag.core.symbolsFileName" value=""/>\r
+<stringAttribute key="org.eclipse.cdt.debug.gdbjtag.core.symbolsOffset" value=""/>\r
+<booleanAttribute key="org.eclipse.cdt.debug.gdbjtag.core.useFileForImage" value="false"/>\r
+<booleanAttribute key="org.eclipse.cdt.debug.gdbjtag.core.useFileForSymbols" value="false"/>\r
+<booleanAttribute key="org.eclipse.cdt.debug.gdbjtag.core.useProjBinaryForImage" value="true"/>\r
+<booleanAttribute key="org.eclipse.cdt.debug.gdbjtag.core.useProjBinaryForSymbols" value="true"/>\r
+<booleanAttribute key="org.eclipse.cdt.debug.gdbjtag.core.useRemoteTarget" value="true"/>\r
+<stringAttribute key="org.eclipse.cdt.dsf.gdb.DEBUG_NAME" value="${cross_prefix}gdb${cross_suffix}"/>\r
+<booleanAttribute key="org.eclipse.cdt.dsf.gdb.UPDATE_THREADLIST_ON_SUSPEND" value="false"/>\r
+<intAttribute key="org.eclipse.cdt.launch.ATTR_BUILD_BEFORE_LAUNCH_ATTR" value="2"/>\r
+<stringAttribute key="org.eclipse.cdt.launch.COREFILE_PATH" value=""/>\r
+<stringAttribute key="org.eclipse.cdt.launch.DEBUGGER_REGISTER_GROUPS" value=""/>\r
+<stringAttribute key="org.eclipse.cdt.launch.PROGRAM_NAME" value="Debug\RTOSDemo.elf"/>\r
+<stringAttribute key="org.eclipse.cdt.launch.PROJECT_ATTR" value="RTOSDemo"/>\r
+<booleanAttribute key="org.eclipse.cdt.launch.PROJECT_BUILD_CONFIG_AUTO_ATTR" value="true"/>\r
+<stringAttribute key="org.eclipse.cdt.launch.PROJECT_BUILD_CONFIG_ID_ATTR" value="ilg.gnumcueclipse.managedbuild.cross.riscv.config.elf.debug.2049051127"/>\r
+<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS">\r
+<listEntry value="/RTOSDemo"/>\r
+</listAttribute>\r
+<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_TYPES">\r
+<listEntry value="4"/>\r
+</listAttribute>\r
+<stringAttribute key="org.eclipse.dsf.launch.MEMORY_BLOCKS" value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <memoryBlockExpressionList context="Context string"/> "/>\r
+<stringAttribute key="process_factory_id" value="org.eclipse.cdt.dsf.gdb.GdbProcessFactory"/>\r
+</launchConfiguration>\r
--- /dev/null
+/*******************************************************************************\r
+ * (c) Copyright 2007-2015 Microsemi SoC Products Group. All rights reserved.\r
+ *\r
+ * IP core registers definitions. This file contains the definitions required\r
+ * for accessing the IP core through the hardware abstraction layer (HAL).\r
+ * This file was automatically generated, using "get_header.exe" version 0.4.0,\r
+ * from the IP-XACT description for:\r
+ *\r
+ * Core16550 version: 2.0.0\r
+ *\r
+ * SVN $Revision: 7963 $\r
+ * SVN $Date: 2015-10-09 17:58:21 +0530 (Fri, 09 Oct 2015) $\r
+ *\r
+ *******************************************************************************/\r
+#ifndef CORE_16550_REGISTERS_H_\r
+#define CORE_16550_REGISTERS_H_ 1\r
+\r
+#ifdef __cplusplus\r
+extern "C" {\r
+#endif\r
+\r
+/*******************************************************************************\r
+ * RBR register:\r
+ *------------------------------------------------------------------------------\r
+ * Receive Buffer Register\r
+ */\r
+#define RBR_REG_OFFSET 0x00U\r
+\r
+/*******************************************************************************\r
+ * THR register:\r
+ *------------------------------------------------------------------------------\r
+ * Transmit Holding Register\r
+ */\r
+#define THR_REG_OFFSET 0x00U\r
+\r
+/*******************************************************************************\r
+ * DLR register:\r
+ *------------------------------------------------------------------------------\r
+ * Divisor Latch(LSB) Register\r
+ */\r
+#define DLR_REG_OFFSET 0x00U\r
+\r
+/*******************************************************************************\r
+ * DMR register:\r
+ *------------------------------------------------------------------------------\r
+ * Divisor Latch(MSB) Register\r
+ */\r
+#define DMR_REG_OFFSET 0x04U\r
+\r
+/*******************************************************************************\r
+ * IER register:\r
+ *------------------------------------------------------------------------------\r
+ * Interrupt Enable Register\r
+ */\r
+#define IER_REG_OFFSET 0x04U\r
+\r
+/*------------------------------------------------------------------------------\r
+ * IER_ERBFI:\r
+ * ERBFI field of register IER.\r
+ *------------------------------------------------------------------------------\r
+ * Enables Received Data Available Interrupt. 0 - Disabled; 1 - Enabled\r
+ */\r
+#define IER_ERBFI_OFFSET 0x04U\r
+#define IER_ERBFI_MASK 0x01U\r
+#define IER_ERBFI_SHIFT 0U\r
+\r
+/*------------------------------------------------------------------------------\r
+ * IER_ETBEI:\r
+ * ETBEI field of register IER.\r
+ *------------------------------------------------------------------------------\r
+ * Enables the Transmitter Holding Register Empty Interrupt. 0 - Disabled; 1 - \r
+ * Enabled\r
+ */\r
+#define IER_ETBEI_OFFSET 0x04U\r
+#define IER_ETBEI_MASK 0x02U\r
+#define IER_ETBEI_SHIFT 1U\r
+\r
+/*------------------------------------------------------------------------------\r
+ * IER_ELSI:\r
+ * ELSI field of register IER.\r
+ *------------------------------------------------------------------------------\r
+ * Enables the Receiver Line Status Interrupt. 0 - Disabled; 1 - Enabled\r
+ */\r
+#define IER_ELSI_OFFSET 0x04U\r
+#define IER_ELSI_MASK 0x04U\r
+#define IER_ELSI_SHIFT 2U\r
+\r
+/*------------------------------------------------------------------------------\r
+ * IER_EDSSI:\r
+ * EDSSI field of register IER.\r
+ *------------------------------------------------------------------------------\r
+ * Enables the Modem Status Interrupt 0 - Disabled; 1 - Enabled\r
+ */\r
+#define IER_EDSSI_OFFSET 0x04U\r
+#define IER_EDSSI_MASK 0x08U\r
+#define IER_EDSSI_SHIFT 3U\r
+\r
+/*******************************************************************************\r
+ * IIR register:\r
+ *------------------------------------------------------------------------------\r
+ * Interrupt Identification\r
+ */\r
+#define IIR_REG_OFFSET 0x08U\r
+\r
+/*------------------------------------------------------------------------------\r
+ * IIR_IIR:\r
+ * IIR field of register IIR.\r
+ *------------------------------------------------------------------------------\r
+ * Interrupt Identification bits.\r
+ */\r
+#define IIR_IIR_OFFSET 0x08U\r
+#define IIR_IIR_MASK 0x0FU\r
+#define IIR_IIR_SHIFT 0U\r
+\r
+/*------------------------------------------------------------------------------\r
+ * IIR_IIR:\r
+ * IIR field of register IIR.\r
+ *------------------------------------------------------------------------------\r
+ * Interrupt Identification bits.\r
+ */\r
+\r
+/*------------------------------------------------------------------------------\r
+ * IIR_Mode:\r
+ * Mode field of register IIR.\r
+ *------------------------------------------------------------------------------\r
+ * 11 - FIFO mode\r
+ */\r
+#define IIR_MODE_OFFSET 0x08U\r
+#define IIR_MODE_MASK 0xC0U\r
+#define IIR_MODE_SHIFT 6U\r
+\r
+/*******************************************************************************\r
+ * FCR register:\r
+ *------------------------------------------------------------------------------\r
+ * FIFO Control Register\r
+ */\r
+#define FCR_REG_OFFSET 0x08\r
+\r
+/*------------------------------------------------------------------------------\r
+ * FCR_Bit0:\r
+ * Bit0 field of register FCR.\r
+ *------------------------------------------------------------------------------\r
+ * This bit enables both the TX and RX FIFOs.\r
+ */\r
+#define FCR_BIT0_OFFSET 0x08U\r
+#define FCR_BIT0_MASK 0x01U\r
+#define FCR_BIT0_SHIFT 0U\r
+\r
+#define FCR_ENABLE_OFFSET 0x08U\r
+#define FCR_ENABLE_MASK 0x01U\r
+#define FCR_ENABLE_SHIFT 0U\r
+\r
+/*------------------------------------------------------------------------------\r
+ * FCR_Bit1:\r
+ * Bit1 field of register FCR.\r
+ *------------------------------------------------------------------------------\r
+ * Clears all bytes in the RX FIFO and resets its counter logic. The shift \r
+ * register is not cleared. 0 - Disabled; 1 - Enabled\r
+ */\r
+#define FCR_BIT1_OFFSET 0x08U\r
+#define FCR_BIT1_MASK 0x02U\r
+#define FCR_BIT1_SHIFT 1U\r
+\r
+#define FCR_CLEAR_RX_OFFSET 0x08U\r
+#define FCR_CLEAR_RX_MASK 0x02U\r
+#define FCR_CLEAR_RX_SHIFT 1U\r
+\r
+/*------------------------------------------------------------------------------\r
+ * FCR_Bit2:\r
+ * Bit2 field of register FCR.\r
+ *------------------------------------------------------------------------------\r
+ * Clears all bytes in the TX FIFO and resets its counter logic. The shift \r
+ * register is not cleared. 0 - Disabled; 1 - Enabled\r
+ */\r
+#define FCR_BIT2_OFFSET 0x08U\r
+#define FCR_BIT2_MASK 0x04U\r
+#define FCR_BIT2_SHIFT 2U\r
+\r
+#define FCR_CLEAR_TX_OFFSET 0x08U\r
+#define FCR_CLEAR_TX_MASK 0x04U\r
+#define FCR_CLEAR_TX_SHIFT 2U\r
+\r
+/*------------------------------------------------------------------------------\r
+ * FCR_Bit3:\r
+ * Bit3 field of register FCR.\r
+ *------------------------------------------------------------------------------\r
+ * Enables RXRDYN and TXRDYN pins when set to 1. Otherwise, they are disabled.\r
+ */\r
+#define FCR_BIT3_OFFSET 0x08U\r
+#define FCR_BIT3_MASK 0x08U\r
+#define FCR_BIT3_SHIFT 3U\r
+\r
+#define FCR_RDYN_EN_OFFSET 0x08U\r
+#define FCR_RDYN_EN_MASK 0x08U\r
+#define FCR_RDYN_EN_SHIFT 3U\r
+\r
+/*------------------------------------------------------------------------------\r
+ * FCR_Bit6:\r
+ * Bit6 field of register FCR.\r
+ *------------------------------------------------------------------------------\r
+ * These bits are used to set the trigger level for the RX FIFO interrupt. RX \r
+ * FIFO Trigger Level: 0 - 1; 1 - 4; 2 - 8; 3 - 14\r
+ */\r
+#define FCR_BIT6_OFFSET 0x08U\r
+#define FCR_BIT6_MASK 0xC0U\r
+#define FCR_BIT6_SHIFT 6U\r
+\r
+#define FCR_TRIG_LEVEL_OFFSET 0x08U\r
+#define FCR_TRIG_LEVEL_MASK 0xC0U\r
+#define FCR_TRIG_LEVEL_SHIFT 6U\r
+\r
+/*******************************************************************************\r
+ * LCR register:\r
+ *------------------------------------------------------------------------------\r
+ * Line Control Register\r
+ */\r
+#define LCR_REG_OFFSET 0x0CU\r
+\r
+/*------------------------------------------------------------------------------\r
+ * LCR_WLS:\r
+ * WLS field of register LCR.\r
+ *------------------------------------------------------------------------------\r
+ * Word Length Select: 00 - 5 bits; 01 - 6 bits; 10 - 7 bits; 11 - 8 bits\r
+ */\r
+#define LCR_WLS_OFFSET 0x0CU\r
+#define LCR_WLS_MASK 0x03U\r
+#define LCR_WLS_SHIFT 0U\r
+\r
+/*------------------------------------------------------------------------------\r
+ * LCR_STB:\r
+ * STB field of register LCR.\r
+ *------------------------------------------------------------------------------\r
+ * Number of Stop Bits: 0 - 1 stop bit; 1 - 1½ stop bits when WLS = 00, 2 stop \r
+ * bits in other cases\r
+ */\r
+#define LCR_STB_OFFSET 0x0CU\r
+#define LCR_STB_MASK 0x04U\r
+#define LCR_STB_SHIFT 2U\r
+\r
+/*------------------------------------------------------------------------------\r
+ * LCR_PEN:\r
+ * PEN field of register LCR.\r
+ *------------------------------------------------------------------------------\r
+ * Parity Enable 0 - Disabled; 1 - Enabled. Parity is added in transmission and \r
+ * checked in receiving.\r
+ */\r
+#define LCR_PEN_OFFSET 0x0CU\r
+#define LCR_PEN_MASK 0x08U\r
+#define LCR_PEN_SHIFT 3U\r
+\r
+/*------------------------------------------------------------------------------\r
+ * LCR_EPS:\r
+ * EPS field of register LCR.\r
+ *------------------------------------------------------------------------------\r
+ * Even Parity Select 0 - Odd parity; 1 - Even parity\r
+ */\r
+#define LCR_EPS_OFFSET 0x0CU\r
+#define LCR_EPS_MASK 0x10U\r
+#define LCR_EPS_SHIFT 4U\r
+\r
+/*------------------------------------------------------------------------------\r
+ * LCR_SP:\r
+ * SP field of register LCR.\r
+ *------------------------------------------------------------------------------\r
+ * Stick Parity 0 - Disabled; 1 - Enabled When stick parity is enabled, it \r
+ * works as follows: Bits 4..3, 11 - 0 will be sent as a parity bit, and \r
+ * checked in receiving. 01 - 1 will be sent as a parity bit, and checked in \r
+ * receiving.\r
+ */\r
+#define LCR_SP_OFFSET 0x0CU\r
+#define LCR_SP_MASK 0x20U\r
+#define LCR_SP_SHIFT 5U\r
+\r
+/*------------------------------------------------------------------------------\r
+ * LCR_SB:\r
+ * SB field of register LCR.\r
+ *------------------------------------------------------------------------------\r
+ * Set Break 0 - Disabled 1 - Set break. SOUT is forced to 0. This does not \r
+ * have any effect on transmitter logic. The break is disabled by setting the \r
+ * bit to 0.\r
+ */\r
+#define LCR_SB_OFFSET 0x0CU\r
+#define LCR_SB_MASK 0x40U\r
+#define LCR_SB_SHIFT 6U\r
+\r
+/*------------------------------------------------------------------------------\r
+ * LCR_DLAB:\r
+ * DLAB field of register LCR.\r
+ *------------------------------------------------------------------------------\r
+ * Divisor Latch Access Bit 0 - Disabled. Normal addressing mode in use 1 - \r
+ * Enabled. Enables access to the Divisor Latch registers during read or write \r
+ * operation to addresses 0 and 1.\r
+ */\r
+#define LCR_DLAB_OFFSET 0x0CU\r
+#define LCR_DLAB_MASK 0x80U\r
+#define LCR_DLAB_SHIFT 7U\r
+\r
+/*******************************************************************************\r
+ * MCR register:\r
+ *------------------------------------------------------------------------------\r
+ * Modem Control Register\r
+ */\r
+#define MCR_REG_OFFSET 0x10U\r
+\r
+/*------------------------------------------------------------------------------\r
+ * MCR_DTR:\r
+ * DTR field of register MCR.\r
+ *------------------------------------------------------------------------------\r
+ * Controls the Data Terminal Ready (DTRn) output. 0 - DTRn <= 1; 1 - DTRn <= 0\r
+ */\r
+#define MCR_DTR_OFFSET 0x10U\r
+#define MCR_DTR_MASK 0x01U\r
+#define MCR_DTR_SHIFT 0U\r
+\r
+/*------------------------------------------------------------------------------\r
+ * MCR_RTS:\r
+ * RTS field of register MCR.\r
+ *------------------------------------------------------------------------------\r
+ * Controls the Request to Send (RTSn) output. 0 - RTSn <= 1; 1 - RTSn <= 0\r
+ */\r
+#define MCR_RTS_OFFSET 0x10U\r
+#define MCR_RTS_MASK 0x02U\r
+#define MCR_RTS_SHIFT 1U\r
+\r
+/*------------------------------------------------------------------------------\r
+ * MCR_Out1:\r
+ * Out1 field of register MCR.\r
+ *------------------------------------------------------------------------------\r
+ * Controls the Output1 (OUT1n) signal. 0 - OUT1n <= 1; 1 - OUT1n <= 0\r
+ */\r
+#define MCR_OUT1_OFFSET 0x10U\r
+#define MCR_OUT1_MASK 0x04U\r
+#define MCR_OUT1_SHIFT 2U\r
+\r
+/*------------------------------------------------------------------------------\r
+ * MCR_Out2:\r
+ * Out2 field of register MCR.\r
+ *------------------------------------------------------------------------------\r
+ * Controls the Output2 (OUT2n) signal. 0 - OUT2n <=1; 1 - OUT2n <=0\r
+ */\r
+#define MCR_OUT2_OFFSET 0x10U\r
+#define MCR_OUT2_MASK 0x08U\r
+#define MCR_OUT2_SHIFT 3U\r
+\r
+/*------------------------------------------------------------------------------\r
+ * MCR_Loop:\r
+ * Loop field of register MCR.\r
+ *------------------------------------------------------------------------------\r
+ * Loop enable bit 0 - Disabled; 1 - Enabled. The following happens in loop \r
+ * mode: SOUT is set to 1. The SIN, DSRn, CTSn, RIn, and DCDn inputs are \r
+ * disconnected. The output of the Transmitter Shift Register is looped back \r
+ * into the Receiver Shift Register. The modem control outputs (DTRn, RTSn, \r
+ * OUT1n, and OUT2n) are connected internally to the modem control inputs, and \r
+ * the modem control output pins are set at 1. In loopback mode, the \r
+ * transmitted data is immediately received, allowing the CPU to check the \r
+ * operation of the UART. The interrupts are operating in loop mode.\r
+ */\r
+#define MCR_LOOP_OFFSET 0x10U\r
+#define MCR_LOOP_MASK 0x10U\r
+#define MCR_LOOP_SHIFT 4U\r
+\r
+/*******************************************************************************\r
+ * LSR register:\r
+ *------------------------------------------------------------------------------\r
+ * Line Status Register\r
+ */\r
+#define LSR_REG_OFFSET 0x14U\r
+\r
+/*------------------------------------------------------------------------------\r
+ * LSR_DR:\r
+ * DR field of register LSR.\r
+ *------------------------------------------------------------------------------\r
+ * Data Ready indicator 1 when a data byte has been received and stored in the \r
+ * FIFO. DR is cleared to 0 when the CPU reads the data from the FIFO.\r
+ */\r
+#define LSR_DR_OFFSET 0x14U\r
+#define LSR_DR_MASK 0x01U\r
+#define LSR_DR_SHIFT 0U\r
+\r
+/*------------------------------------------------------------------------------\r
+ * LSR_OE:\r
+ * OE field of register LSR.\r
+ *------------------------------------------------------------------------------\r
+ * Overrun Error indicator Indicates that the new byte was received before the \r
+ * CPU read the byte from the receive buffer, and that the earlier data byte \r
+ * was destroyed. OE is cleared when the CPU reads the Line Status Register. If \r
+ * the data continues to fill the FIFO beyond the trigger level, an overrun \r
+ * error will occur once the FIFO is full and the next character has been \r
+ * completely received in the shift register. The character in the shift \r
+ * register is overwritten, but it is not transferred to the FIFO.\r
+ */\r
+#define LSR_OE_OFFSET 0x14U\r
+#define LSR_OE_MASK 0x02U\r
+#define LSR_OE_SHIFT 1U\r
+\r
+/*------------------------------------------------------------------------------\r
+ * LSR_PE:\r
+ * PE field of register LSR.\r
+ *------------------------------------------------------------------------------\r
+ * Parity Error indicator Indicates that the received byte had a parity error. \r
+ * PE is cleared when the CPU reads the Line Status Register. This error is \r
+ * revealed to the CPU when its associated character is at the top of the FIFO.\r
+ */\r
+#define LSR_PE_OFFSET 0x14U\r
+#define LSR_PE_MASK 0x04U\r
+#define LSR_PE_SHIFT 2U\r
+\r
+/*------------------------------------------------------------------------------\r
+ * LSR_FE:\r
+ * FE field of register LSR.\r
+ *------------------------------------------------------------------------------\r
+ * Framing Error indicator Indicates that the received byte did not have a \r
+ * valid Stop bit. FE is cleared when the CPU reads the Line Status Register. \r
+ * The UART will try to re-synchronize after a framing error. To do this, it\r
+ * assumes that the framing error was due to the next start bit, so it samples \r
+ * this start bit twice, and then starts receiving the data. This error is \r
+ * revealed to the CPU when its associated character is at the top of the FIFO.\r
+ */\r
+#define LSR_FE_OFFSET 0x14U\r
+#define LSR_FE_MASK 0x08U\r
+#define LSR_FE_SHIFT 3U\r
+\r
+/*------------------------------------------------------------------------------\r
+ * LSR_BI:\r
+ * BI field of register LSR.\r
+ *------------------------------------------------------------------------------\r
+ * Break Interrupt indicator Indicates that the received data is at 0 longer \r
+ * than a full word transmission time (start bit + data bits + parity + stop \r
+ * bits). BI is cleared when the CPU reads the Line Status Register. This error \r
+ * is revealed to the CPU when its associated character is at the top of the \r
+ * FIFO. When break occurs, only one zero character is loaded into the FIFO.\r
+ */\r
+#define LSR_BI_OFFSET 0x14U\r
+#define LSR_BI_MASK 0x10U\r
+#define LSR_BI_SHIFT 4U\r
+\r
+/*------------------------------------------------------------------------------\r
+ * LSR_THRE:\r
+ * THRE field of register LSR.\r
+ *------------------------------------------------------------------------------\r
+ * Transmitter Holding Register Empty indicator Indicates that the UART is \r
+ * ready to transmit a new data byte. THRE causes an interrupt to the CPU when \r
+ * bit 1 (ETBEI) in the Interrupt Enable Register is 1. This bit is set when \r
+ * the TX FIFO is empty. It is cleared when at least one byte is written to the \r
+ * TX FIFO.\r
+ */\r
+#define LSR_THRE_OFFSET 0x14U\r
+#define LSR_THRE_MASK 0x20U\r
+#define LSR_THRE_SHIFT 5U\r
+\r
+/*------------------------------------------------------------------------------\r
+ * LSR_TEMT:\r
+ * TEMT field of register LSR.\r
+ *------------------------------------------------------------------------------\r
+ * Transmitter Empty indicator This bit is set to 1 when both the transmitter \r
+ * FIFO and shift registers are empty.\r
+ */\r
+#define LSR_TEMT_OFFSET 0x14U\r
+#define LSR_TEMT_MASK 0x40U\r
+#define LSR_TEMT_SHIFT 6U\r
+\r
+/*------------------------------------------------------------------------------\r
+ * LSR_FIER:\r
+ * FIER field of register LSR.\r
+ *------------------------------------------------------------------------------\r
+ * This bit is set when there is at least one parity error, framing error, or \r
+ * break indication in the FIFO. FIER is cleared when the CPU reads the LSR if \r
+ * there are no subsequent errors in the FIFO.\r
+ */\r
+#define LSR_FIER_OFFSET 0x14U\r
+#define LSR_FIER_MASK 0x80U\r
+#define LSR_FIER_SHIFT 7U\r
+\r
+/*******************************************************************************\r
+ * MSR register:\r
+ *------------------------------------------------------------------------------\r
+ * Modem Status Register\r
+ */\r
+#define MSR_REG_OFFSET 0x18U\r
+\r
+/*------------------------------------------------------------------------------\r
+ * MSR_DCTS:\r
+ * DCTS field of register MSR.\r
+ *------------------------------------------------------------------------------\r
+ * Delta Clear to Send indicator. Indicates that the CTSn input has changed \r
+ * state since the last time it was read by the CPU.\r
+ */\r
+#define MSR_DCTS_OFFSET 0x18U\r
+#define MSR_DCTS_MASK 0x01U\r
+#define MSR_DCTS_SHIFT 0U\r
+\r
+/*------------------------------------------------------------------------------\r
+ * MSR_DDSR:\r
+ * DDSR field of register MSR.\r
+ *------------------------------------------------------------------------------\r
+ * Delta Data Set Ready indicator Indicates that the DSRn input has changed \r
+ * state since the last time it was read by the CPU.\r
+ */\r
+#define MSR_DDSR_OFFSET 0x18U\r
+#define MSR_DDSR_MASK 0x02U\r
+#define MSR_DDSR_SHIFT 1U\r
+\r
+/*------------------------------------------------------------------------------\r
+ * MSR_TERI:\r
+ * TERI field of register MSR.\r
+ *------------------------------------------------------------------------------\r
+ * Trailing Edge of Ring Indicator detector. Indicates that RI input has \r
+ * changed from 0 to 1.\r
+ */\r
+#define MSR_TERI_OFFSET 0x18U\r
+#define MSR_TERI_MASK 0x04U\r
+#define MSR_TERI_SHIFT 2U\r
+\r
+/*------------------------------------------------------------------------------\r
+ * MSR_DDCD:\r
+ * DDCD field of register MSR.\r
+ *------------------------------------------------------------------------------\r
+ * Delta Data Carrier Detect indicator Indicates that DCD input has changed \r
+ * state. NOTE: Whenever bit 0, 1, 2, or 3 is set to 1, a Modem Status \r
+ * Interrupt is generated.\r
+ */\r
+#define MSR_DDCD_OFFSET 0x18U\r
+#define MSR_DDCD_MASK 0x08U\r
+#define MSR_DDCD_SHIFT 3U\r
+\r
+/*------------------------------------------------------------------------------\r
+ * MSR_CTS:\r
+ * CTS field of register MSR.\r
+ *------------------------------------------------------------------------------\r
+ * Clear to Send The complement of the CTSn input. When bit 4 of the Modem \r
+ * Control Register (MCR) is set to 1 (loop), this bit is equivalent to DTR in \r
+ * the MCR.\r
+ */\r
+#define MSR_CTS_OFFSET 0x18U\r
+#define MSR_CTS_MASK 0x10U\r
+#define MSR_CTS_SHIFT 4U\r
+\r
+/*------------------------------------------------------------------------------\r
+ * MSR_DSR:\r
+ * DSR field of register MSR.\r
+ *------------------------------------------------------------------------------\r
+ * Data Set Ready The complement of the DSR input. When bit 4 of the MCR is set \r
+ * to 1 (loop), this bit is equivalent to RTSn in the MCR.\r
+ */\r
+#define MSR_DSR_OFFSET 0x18U\r
+#define MSR_DSR_MASK 0x20U\r
+#define MSR_DSR_SHIFT 5U\r
+\r
+/*------------------------------------------------------------------------------\r
+ * MSR_RI:\r
+ * RI field of register MSR.\r
+ *------------------------------------------------------------------------------\r
+ * Ring Indicator The complement of the RIn input. When bit 4 of the MCR is set \r
+ * to 1 (loop), this bit is equivalent to OUT1 in the MCR.\r
+ */\r
+#define MSR_RI_OFFSET 0x18U\r
+#define MSR_RI_MASK 0x40U\r
+#define MSR_RI_SHIFT 6U\r
+\r
+/*------------------------------------------------------------------------------\r
+ * MSR_DCD:\r
+ * DCD field of register MSR.\r
+ *------------------------------------------------------------------------------\r
+ * Data Carrier Detect The complement of DCDn input. When bit 4 of the MCR is \r
+ * set to 1 (loop), this bit is equivalent to OUT2 in the MCR.\r
+ */\r
+#define MSR_DCD_OFFSET 0x18U\r
+#define MSR_DCD_MASK 0x80U\r
+#define MSR_DCD_SHIFT 7U\r
+\r
+/*******************************************************************************\r
+ * SR register:\r
+ *------------------------------------------------------------------------------\r
+ * Scratch Register\r
+ */\r
+#define SR_REG_OFFSET 0x1CU\r
+\r
+#ifdef __cplusplus\r
+}\r
+#endif\r
+\r
+#endif /* CORE_16550_REGISTERS_H_*/\r
--- /dev/null
+/*******************************************************************************\r
+ * (c) Copyright 2007-2015 Microsemi SoC Products Group. All rights reserved.\r
+ *\r
+ * Core16550 driver implementation. See file "core_16550.h" for a\r
+ * description of the functions implemented in this file.\r
+ *\r
+ * SVN $Revision: 7963 $\r
+ * SVN $Date: 2015-10-09 17:58:21 +0530 (Fri, 09 Oct 2015) $\r
+ */\r
+#include "hal.h"\r
+#include "core_16550.h"\r
+#include "core16550_regs.h"\r
+#include "hal_assert.h"\r
+\r
+#ifdef __cplusplus\r
+extern "C" {\r
+#endif\r
+\r
+/*******************************************************************************\r
+ * Definitions for transmitter states\r
+ */\r
+#define TX_COMPLETE 0x00U\r
+\r
+/*******************************************************************************\r
+ * Definition for transmitter FIFO size\r
+ */\r
+#define TX_FIFO_SIZE 16U\r
+\r
+/*******************************************************************************\r
+ * Default receive interrupt trigger level\r
+ */\r
+#define DEFAULT_RX_TRIG_LEVEL ((uint8_t)UART_16550_FIFO_SINGLE_BYTE)\r
+\r
+/*******************************************************************************\r
+ * Receiver error status mask and shift offset\r
+ */\r
+#define STATUS_ERROR_MASK ( LSR_OE_MASK | LSR_PE_MASK | \\r
+ LSR_FE_MASK | LSR_BI_MASK | LSR_FIER_MASK)\r
+\r
+/*******************************************************************************\r
+ * Definitions for invalid parameters with proper type\r
+ */\r
+#define INVALID_INTERRUPT 0U\r
+#define INVALID_IRQ_HANDLER ( (uart_16550_irq_handler_t) 0 )\r
+\r
+/*******************************************************************************\r
+ * Possible values for Interrupt Identification Register Field.\r
+ */\r
+#define IIRF_MODEM_STATUS 0x00U\r
+#define IIRF_THRE 0x02U\r
+#define IIRF_RX_DATA 0x04U\r
+#define IIRF_RX_LINE_STATUS 0x06U\r
+#define IIRF_DATA_TIMEOUT 0x0CU\r
+\r
+/*******************************************************************************\r
+ * Null parameters with appropriate type definitions\r
+ */\r
+#define NULL_ADDR ( ( addr_t ) 0 )\r
+#define NULL_INSTANCE ( ( uart_16550_instance_t * ) 0 )\r
+#define NULL_BUFF ( ( uint8_t * ) 0 )\r
+\r
+/*******************************************************************************\r
+ * Possible states for different register bit fields\r
+ */\r
+enum {\r
+ DISABLE = 0U,\r
+ ENABLE = 1U\r
+};\r
+\r
+/*******************************************************************************\r
+ * Static function declarations\r
+ */\r
+static void default_tx_handler(uart_16550_instance_t * this_uart);\r
+\r
+/*******************************************************************************\r
+ * Public function definitions\r
+ */\r
+\r
+/***************************************************************************//**\r
+ * UART_16550_init.\r
+ * See core_16550.h for details of how to use this function.\r
+ */\r
+void\r
+UART_16550_init\r
+(\r
+ uart_16550_instance_t* this_uart,\r
+ addr_t base_addr,\r
+ uint16_t baud_value,\r
+ uint8_t line_config\r
+)\r
+{\r
+#ifndef NDEBUG\r
+ uint8_t dbg1;\r
+ uint8_t dbg2;\r
+#endif\r
+ uint8_t fifo_config;\r
+ uint8_t temp;\r
+\r
+ HAL_ASSERT( base_addr != NULL_ADDR );\r
+ HAL_ASSERT( this_uart != NULL_INSTANCE );\r
+\r
+ if( ( base_addr != NULL_ADDR ) && ( this_uart != NULL_INSTANCE ) )\r
+ {\r
+ /* disable interrupts */\r
+ HAL_set_8bit_reg(base_addr, IER, DISABLE);\r
+\r
+ /* reset divisor latch */\r
+ HAL_set_8bit_reg_field(base_addr, LCR_DLAB, ENABLE);\r
+#ifndef NDEBUG\r
+ dbg1 = HAL_get_8bit_reg_field(base_addr, LCR_DLAB );\r
+ HAL_ASSERT( dbg1 == ENABLE );\r
+#endif\r
+ /* MSB of baud value */\r
+ temp = (uint8_t)(baud_value >> 8);\r
+ HAL_set_8bit_reg(base_addr, DMR, temp );\r
+ /* LSB of baud value */\r
+ HAL_set_8bit_reg(base_addr, DLR, ( (uint8_t)baud_value ) );\r
+#ifndef NDEBUG\r
+ dbg1 = HAL_get_8bit_reg(base_addr, DMR );\r
+ dbg2 = HAL_get_8bit_reg(base_addr, DLR );\r
+ HAL_ASSERT( ( ( ( (uint16_t) dbg1 ) << 8 ) | dbg2 ) == baud_value );\r
+#endif\r
+ /* reset divisor latch */\r
+ HAL_set_8bit_reg_field(base_addr, LCR_DLAB, DISABLE);\r
+#ifndef NDEBUG\r
+ dbg1 = HAL_get_8bit_reg_field(base_addr, LCR_DLAB );\r
+ HAL_ASSERT( dbg1 == DISABLE );\r
+#endif\r
+ /* set the line control register (bit length, stop bits, parity) */\r
+ HAL_set_8bit_reg( base_addr, LCR, line_config );\r
+#ifndef NDEBUG\r
+ dbg1 = HAL_get_8bit_reg(base_addr, LCR );\r
+ HAL_ASSERT( dbg1 == line_config)\r
+#endif\r
+ /* Enable and configure the RX and TX FIFOs. */\r
+ fifo_config = ((uint8_t)(DEFAULT_RX_TRIG_LEVEL << FCR_TRIG_LEVEL_SHIFT) |\r
+ FCR_RDYN_EN_MASK | FCR_CLEAR_RX_MASK |\r
+ FCR_CLEAR_TX_MASK | FCR_ENABLE_MASK );\r
+ HAL_set_8bit_reg( base_addr, FCR, fifo_config );\r
+\r
+ /* disable loopback */\r
+ HAL_set_8bit_reg_field( base_addr, MCR_LOOP, DISABLE );\r
+#ifndef NDEBUG\r
+ dbg1 = HAL_get_8bit_reg_field(base_addr, MCR_LOOP);\r
+ HAL_ASSERT( dbg1 == DISABLE );\r
+#endif\r
+\r
+ /* Instance setup */\r
+ this_uart->base_address = base_addr;\r
+ this_uart->tx_buffer = NULL_BUFF;\r
+ this_uart->tx_buff_size = TX_COMPLETE;\r
+ this_uart->tx_idx = 0U;\r
+ this_uart->tx_handler = default_tx_handler;\r
+\r
+ this_uart->rx_handler = ( (uart_16550_irq_handler_t) 0 );\r
+ this_uart->linests_handler = ( (uart_16550_irq_handler_t) 0 );\r
+ this_uart->modemsts_handler = ( (uart_16550_irq_handler_t) 0 );\r
+ this_uart->status = 0U;\r
+ }\r
+}\r
+\r
+/***************************************************************************//**\r
+ * UART_16550_polled_tx.\r
+ * See core_16550.h for details of how to use this function.\r
+ */\r
+void\r
+UART_16550_polled_tx\r
+(\r
+ uart_16550_instance_t * this_uart,\r
+ const uint8_t * pbuff,\r
+ uint32_t tx_size\r
+)\r
+{\r
+ uint32_t char_idx = 0U;\r
+ uint32_t size_sent;\r
+ uint8_t status;\r
+\r
+ HAL_ASSERT( this_uart != NULL_INSTANCE );\r
+ HAL_ASSERT( pbuff != NULL_BUFF );\r
+ HAL_ASSERT( tx_size > 0U );\r
+\r
+ if( ( this_uart != NULL_INSTANCE ) &&\r
+ ( pbuff != NULL_BUFF ) &&\r
+ ( tx_size > 0U ) )\r
+ {\r
+ /* Remain in this loop until the entire input buffer\r
+ * has been transferred to the UART.\r
+ */\r
+ do {\r
+ /* Read the Line Status Register and update the sticky record */\r
+ status = HAL_get_8bit_reg( this_uart->base_address, LSR );\r
+ this_uart->status |= status;\r
+\r
+ /* Check if TX FIFO is empty. */\r
+ if( status & LSR_THRE_MASK )\r
+ {\r
+ uint32_t fill_size = TX_FIFO_SIZE;\r
+\r
+ /* Calculate the number of bytes to transmit. */\r
+ if ( tx_size < TX_FIFO_SIZE )\r
+ {\r
+ fill_size = tx_size;\r
+ }\r
+\r
+ /* Fill the TX FIFO with the calculated the number of bytes. */\r
+ for ( size_sent = 0U; size_sent < fill_size; ++size_sent )\r
+ {\r
+ /* Send next character in the buffer. */\r
+ HAL_set_8bit_reg( this_uart->base_address, THR,\r
+ (uint_fast8_t)pbuff[char_idx++]);\r
+ }\r
+\r
+ /* Calculate the number of untransmitted bytes remaining. */\r
+ tx_size -= size_sent;\r
+ }\r
+ } while ( tx_size );\r
+ }\r
+}\r
+\r
+/***************************************************************************//**\r
+ * UART_16550_polled_tx_string.\r
+ * See core_16550.h for details of how to use this function.\r
+ */\r
+void\r
+UART_16550_polled_tx_string\r
+(\r
+ uart_16550_instance_t * this_uart,\r
+ const uint8_t * p_sz_string\r
+)\r
+{\r
+ uint32_t char_idx = 0U;\r
+ uint32_t fill_size;\r
+ uint_fast8_t data_byte;\r
+ uint8_t status;\r
+\r
+ HAL_ASSERT( this_uart != NULL_INSTANCE );\r
+ HAL_ASSERT( p_sz_string != NULL_BUFF );\r
+\r
+ if( ( this_uart != NULL_INSTANCE ) && ( p_sz_string != NULL_BUFF ) )\r
+ {\r
+ char_idx = 0U;\r
+\r
+ /* Get the first data byte from the input buffer */\r
+ data_byte = (uint_fast8_t)p_sz_string[char_idx];\r
+\r
+ /* First check for the NULL terminator byte.\r
+ * Then remain in this loop until the entire string in the input buffer\r
+ * has been transferred to the UART.\r
+ */\r
+ while ( 0U != data_byte )\r
+ {\r
+ /* Wait until TX FIFO is empty. */\r
+ do {\r
+ status = HAL_get_8bit_reg( this_uart->base_address,LSR);\r
+ this_uart->status |= status;\r
+ } while ( !( status & LSR_THRE_MASK ) );\r
+\r
+ /* Send bytes from the input buffer until the TX FIFO is full\r
+ * or we reach the NULL terminator byte.\r
+ */\r
+ fill_size = 0U;\r
+ while ( (0U != data_byte) && (fill_size < TX_FIFO_SIZE) )\r
+ {\r
+ /* Send the data byte */\r
+ HAL_set_8bit_reg( this_uart->base_address, THR, data_byte );\r
+ ++fill_size;\r
+ char_idx++;\r
+ /* Get the next data byte from the input buffer */\r
+ data_byte = (uint_fast8_t)p_sz_string[char_idx];\r
+ }\r
+ }\r
+ }\r
+}\r
+\r
+\r
+/***************************************************************************//**\r
+ * UART_16550_irq_tx.\r
+ * See core_16550.h for details of how to use this function.\r
+ */\r
+void\r
+UART_16550_irq_tx\r
+(\r
+ uart_16550_instance_t * this_uart,\r
+ const uint8_t * pbuff,\r
+ uint32_t tx_size\r
+)\r
+{\r
+ HAL_ASSERT( this_uart != NULL_INSTANCE )\r
+ HAL_ASSERT( pbuff != NULL_BUFF )\r
+ HAL_ASSERT( tx_size > 0U )\r
+\r
+ if( ( this_uart != NULL_INSTANCE ) &&\r
+ ( pbuff != NULL_BUFF ) &&\r
+ ( tx_size > 0U ) )\r
+ {\r
+ /*Initialize the UART instance with\r
+ parameters required for transmission.*/\r
+ this_uart->tx_buffer = pbuff;\r
+ this_uart->tx_buff_size = tx_size;\r
+ /* char_idx; */\r
+ this_uart->tx_idx = 0U;\r
+ /* assign handler for default data transmission */\r
+ this_uart->tx_handler = default_tx_handler;\r
+\r
+ /* enables TX interrupt */\r
+ HAL_set_8bit_reg_field(this_uart->base_address, IER_ETBEI, ENABLE);\r
+ }\r
+}\r
+\r
+/***************************************************************************//**\r
+ * UART_16550_tx_complete.\r
+ * See core_16550.h for details of how to use this function.\r
+ */\r
+int8_t\r
+UART_16550_tx_complete\r
+(\r
+ uart_16550_instance_t * this_uart\r
+)\r
+{\r
+ int8_t returnvalue = 0;\r
+ uint8_t status = 0U;\r
+\r
+ HAL_ASSERT( this_uart != NULL_INSTANCE )\r
+\r
+ if( this_uart != NULL_INSTANCE )\r
+ {\r
+ status = HAL_get_8bit_reg(this_uart->base_address,LSR);\r
+ this_uart->status |= status;\r
+\r
+ if( ( this_uart->tx_buff_size == TX_COMPLETE ) &&\r
+ ( status & LSR_TEMT_MASK ) )\r
+ {\r
+ returnvalue = (int8_t)1;\r
+ }\r
+ }\r
+ return returnvalue;\r
+}\r
+\r
+\r
+/***************************************************************************//**\r
+ * UART_16550_get_rx.\r
+ * See core_16550.h for details of how to use this function.\r
+ */\r
+size_t\r
+UART_16550_get_rx\r
+(\r
+ uart_16550_instance_t * this_uart,\r
+ uint8_t * rx_buff,\r
+ size_t buff_size\r
+)\r
+{\r
+ uint8_t status;\r
+ size_t rx_size = 0U;\r
+\r
+ HAL_ASSERT( this_uart != NULL_INSTANCE )\r
+ HAL_ASSERT( rx_buff != (uint8_t *)0 )\r
+ HAL_ASSERT( buff_size > 0U )\r
+\r
+ if( ( this_uart != NULL_INSTANCE ) &&\r
+ ( rx_buff != (uint8_t *)0 ) &&\r
+ ( buff_size > 0U ) )\r
+ {\r
+ status = HAL_get_8bit_reg( this_uart->base_address, LSR );\r
+ this_uart->status |= status;\r
+ while ( ((status & LSR_DR_MASK) != 0U) && ( rx_size < buff_size ) )\r
+ {\r
+ rx_buff[rx_size] = HAL_get_8bit_reg( this_uart->base_address, RBR );\r
+ rx_size++;\r
+ status = HAL_get_8bit_reg( this_uart->base_address, LSR );\r
+ this_uart->status |= status;\r
+ }\r
+ }\r
+ return rx_size;\r
+}\r
+\r
+/***************************************************************************//**\r
+ * UART_16550_isr.\r
+ * See core_16550.h for details of how to use this function.\r
+ */\r
+void\r
+UART_16550_isr\r
+(\r
+ uart_16550_instance_t * this_uart\r
+)\r
+{\r
+ uint8_t iirf;\r
+\r
+ HAL_ASSERT( this_uart != NULL_INSTANCE )\r
+\r
+ if(this_uart != NULL_INSTANCE )\r
+ {\r
+ iirf = HAL_get_8bit_reg_field( this_uart->base_address, IIR_IIR );\r
+\r
+ switch ( iirf )\r
+ {\r
+ /* Modem status interrupt */\r
+ case IIRF_MODEM_STATUS:\r
+ {\r
+ if( INVALID_IRQ_HANDLER != this_uart->modemsts_handler )\r
+ {\r
+ HAL_ASSERT( INVALID_IRQ_HANDLER != this_uart->modemsts_handler );\r
+ if( INVALID_IRQ_HANDLER != this_uart->modemsts_handler )\r
+ {\r
+ (*(this_uart->modemsts_handler))(this_uart);\r
+ }\r
+ }\r
+ }\r
+ break;\r
+ /* Transmitter Holding Register Empty interrupt */\r
+ case IIRF_THRE:\r
+ {\r
+ HAL_ASSERT( INVALID_IRQ_HANDLER != this_uart->tx_handler );\r
+ if ( INVALID_IRQ_HANDLER != this_uart->tx_handler )\r
+ {\r
+ (*(this_uart->tx_handler))(this_uart);\r
+ }\r
+ }\r
+ break;\r
+ /* Received Data Available interrupt */\r
+ case IIRF_RX_DATA:\r
+ case IIRF_DATA_TIMEOUT:\r
+ {\r
+ HAL_ASSERT( INVALID_IRQ_HANDLER != this_uart->rx_handler );\r
+ if ( INVALID_IRQ_HANDLER != this_uart->rx_handler )\r
+ {\r
+ (*(this_uart->rx_handler))(this_uart);\r
+ }\r
+ }\r
+ break;\r
+ /* Line status interrupt */\r
+ case IIRF_RX_LINE_STATUS:\r
+ {\r
+ HAL_ASSERT( INVALID_IRQ_HANDLER != this_uart->linests_handler );\r
+ if ( INVALID_IRQ_HANDLER != this_uart->linests_handler )\r
+ {\r
+ (*(this_uart->linests_handler))(this_uart);\r
+ }\r
+ }\r
+ break;\r
+ /* Unidentified interrupt */\r
+ default:\r
+ {\r
+ HAL_ASSERT( INVALID_INTERRUPT )\r
+ }\r
+ }\r
+ }\r
+}\r
+\r
+/***************************************************************************//**\r
+ * UART_16550_set_rx_handler.\r
+ * See core_16550.h for details of how to use this function.\r
+ */\r
+void\r
+UART_16550_set_rx_handler\r
+(\r
+ uart_16550_instance_t * this_uart,\r
+ uart_16550_irq_handler_t handler,\r
+ uart_16550_rx_trig_level_t trigger_level\r
+)\r
+{\r
+ HAL_ASSERT( this_uart != NULL_INSTANCE )\r
+ HAL_ASSERT( handler != INVALID_IRQ_HANDLER)\r
+ HAL_ASSERT( trigger_level < UART_16550_FIFO_INVALID_TRIG_LEVEL)\r
+\r
+ if( ( this_uart != NULL_INSTANCE ) &&\r
+ ( handler != INVALID_IRQ_HANDLER) &&\r
+ ( trigger_level < UART_16550_FIFO_INVALID_TRIG_LEVEL) )\r
+ {\r
+ this_uart->rx_handler = handler;\r
+\r
+ /* Set the receive interrupt trigger level. */\r
+ HAL_set_8bit_reg_field( this_uart->base_address,\r
+ FCR_TRIG_LEVEL, trigger_level );\r
+\r
+ /* Enable receive interrupt. */\r
+ HAL_set_8bit_reg_field( this_uart->base_address, IER_ERBFI, ENABLE );\r
+ }\r
+}\r
+\r
+/***************************************************************************//**\r
+ * UART_16550_set_loopback.\r
+ * See core_16550.h for details of how to use this function.\r
+ */\r
+void\r
+UART_16550_set_loopback\r
+(\r
+ uart_16550_instance_t * this_uart,\r
+ uart_16550_loopback_t loopback\r
+)\r
+{\r
+ HAL_ASSERT( this_uart != NULL_INSTANCE );\r
+ HAL_ASSERT( loopback < UART_16550_INVALID_LOOPBACK );\r
+\r
+ if( ( this_uart != NULL_INSTANCE ) &&\r
+ ( loopback < UART_16550_INVALID_LOOPBACK ) )\r
+ {\r
+ if ( loopback == UART_16550_LOOPBACK_OFF )\r
+ {\r
+ HAL_set_8bit_reg_field( this_uart->base_address,\r
+ MCR_LOOP,\r
+ DISABLE );\r
+ }\r
+ else\r
+ {\r
+ HAL_set_8bit_reg_field( this_uart->base_address,\r
+ MCR_LOOP,\r
+ ENABLE );\r
+ }\r
+ }\r
+}\r
+\r
+/***************************************************************************//**\r
+ * UART_16550_get_rx_status.\r
+ * See core_16550.h for details of how to use this function.\r
+ */\r
+uint8_t\r
+UART_16550_get_rx_status\r
+(\r
+ uart_16550_instance_t * this_uart\r
+)\r
+{\r
+ uint8_t status = UART_16550_INVALID_PARAM;\r
+ HAL_ASSERT( this_uart != NULL_INSTANCE );\r
+\r
+ if( ( this_uart != NULL_INSTANCE ) )\r
+ {\r
+ /*\r
+ * Bit 1 - Overflow error status\r
+ * Bit 2 - Parity error status\r
+ * Bit 3 - Frame error status\r
+ * Bit 4 - Break interrupt indicator\r
+ * Bit 7 - FIFO data error status\r
+ */\r
+ this_uart->status |= HAL_get_8bit_reg( this_uart->base_address, LSR );\r
+ status = ( this_uart->status & STATUS_ERROR_MASK );\r
+ /*\r
+ * Clear the sticky status for this instance.\r
+ */\r
+ this_uart->status = (uint8_t)0;\r
+ }\r
+ return status;\r
+}\r
+\r
+/***************************************************************************//**\r
+ * UART_16550_get_modem_status.\r
+ * See core_16550.h for details of how to use this function.\r
+ */\r
+uint8_t\r
+UART_16550_get_modem_status\r
+(\r
+ uart_16550_instance_t * this_uart\r
+)\r
+{\r
+ uint8_t status = UART_16550_NO_ERROR;\r
+ HAL_ASSERT( this_uart != NULL_INSTANCE )\r
+\r
+ if( ( this_uart != NULL_INSTANCE ) )\r
+ {\r
+ /*\r
+ * Extract UART error status and place in lower bits of "status".\r
+ * Bit 0 - Delta Clear to Send Indicator\r
+ * Bit 1 - Delta Clear to Receive Indicator\r
+ * Bit 2 - Trailing edge of Ring Indicator detector\r
+ * Bit 3 - Delta Data Carrier Detect indicator\r
+ * Bit 4 - Clear To Send\r
+ * Bit 5 - Data Set Ready\r
+ * Bit 6 - Ring Indicator\r
+ * Bit 7 - Data Carrier Detect\r
+ */\r
+ status = HAL_get_8bit_reg( this_uart->base_address, MSR );\r
+ }\r
+ return status;\r
+}\r
+\r
+/***************************************************************************//**\r
+ * Default TX interrupt handler to automatically transmit data from\r
+ * user assgined TX buffer.\r
+ */\r
+static void\r
+default_tx_handler\r
+(\r
+ uart_16550_instance_t * this_uart\r
+)\r
+{\r
+ uint8_t status;\r
+\r
+ HAL_ASSERT( NULL_INSTANCE != this_uart )\r
+\r
+ if ( this_uart != NULL_INSTANCE )\r
+ {\r
+ HAL_ASSERT( NULL_BUFF != this_uart->tx_buffer )\r
+ HAL_ASSERT( 0U != this_uart->tx_buff_size )\r
+\r
+ if ( ( this_uart->tx_buffer != NULL_BUFF ) &&\r
+ ( 0U != this_uart->tx_buff_size ) )\r
+ {\r
+ /* Read the Line Status Register and update the sticky record. */\r
+ status = HAL_get_8bit_reg( this_uart->base_address,LSR);\r
+ this_uart->status |= status;\r
+ \r
+ /*\r
+ * This function should only be called as a result of a THRE interrupt.\r
+ * Verify that this is true before proceeding to transmit data.\r
+ */\r
+ if ( status & LSR_THRE_MASK )\r
+ {\r
+ uint32_t size_sent = 0U;\r
+ uint32_t fill_size = TX_FIFO_SIZE;\r
+ uint32_t tx_remain = this_uart->tx_buff_size - this_uart->tx_idx;\r
+ \r
+ /* Calculate the number of bytes to transmit. */\r
+ if ( tx_remain < TX_FIFO_SIZE )\r
+ {\r
+ fill_size = tx_remain;\r
+ }\r
+ \r
+ /* Fill the TX FIFO with the calculated the number of bytes. */\r
+ for ( size_sent = 0U; size_sent < fill_size; ++size_sent )\r
+ {\r
+ /* Send next character in the buffer. */\r
+ HAL_set_8bit_reg( this_uart->base_address, THR,\r
+ (uint_fast8_t)this_uart->tx_buffer[this_uart->tx_idx]);\r
+ ++this_uart->tx_idx;\r
+ }\r
+ }\r
+ \r
+ /* Flag Tx as complete if all data has been pushed into the Tx FIFO. */\r
+ if ( this_uart->tx_idx == this_uart->tx_buff_size )\r
+ {\r
+ this_uart->tx_buff_size = TX_COMPLETE;\r
+ /* disables TX interrupt */\r
+ HAL_set_8bit_reg_field( this_uart->base_address,\r
+ IER_ETBEI, DISABLE);\r
+ }\r
+ }\r
+ }\r
+}\r
+\r
+/***************************************************************************//**\r
+ * UART_16550_enable_irq.\r
+ * See core_16550.h for details of how to use this function.\r
+ */\r
+void\r
+UART_16550_enable_irq\r
+(\r
+ uart_16550_instance_t * this_uart,\r
+ uint8_t irq_mask\r
+)\r
+{\r
+ HAL_ASSERT( this_uart != NULL_INSTANCE )\r
+\r
+ if( this_uart != NULL_INSTANCE )\r
+ {\r
+ /* irq_mask encoding: 1- enable\r
+ * bit 0 - Receive Data Available Interrupt\r
+ * bit 1 - Transmitter Holding Register Empty Interrupt\r
+ * bit 2 - Receiver Line Status Interrupt\r
+ * bit 3 - Modem Status Interrupt\r
+ */\r
+ /* read present interrupts for enabled ones*/\r
+ irq_mask |= HAL_get_8bit_reg( this_uart->base_address, IER );\r
+ /* Enable interrupts */\r
+ HAL_set_8bit_reg( this_uart->base_address, IER, irq_mask );\r
+ }\r
+}\r
+\r
+/***************************************************************************//**\r
+ * UART_16550_disable_irq.\r
+ * See core_16550.h for details of how to use this function.\r
+ */\r
+void\r
+UART_16550_disable_irq\r
+(\r
+ uart_16550_instance_t * this_uart,\r
+ uint8_t irq_mask\r
+)\r
+{\r
+ HAL_ASSERT( this_uart != NULL_INSTANCE )\r
+\r
+ if( this_uart != NULL_INSTANCE )\r
+ {\r
+ /* irq_mask encoding: 1 - disable\r
+ * bit 0 - Receive Data Available Interrupt\r
+ * bit 1 - Transmitter Holding Register Empty Interrupt\r
+ * bit 2 - Receiver Line Status Interrupt\r
+ * bit 3 - Modem Status Interrupt\r
+ */\r
+ /* read present interrupts for enabled ones */\r
+ irq_mask = (( (uint8_t)~irq_mask ) & \r
+ HAL_get_8bit_reg( this_uart->base_address, IER ));\r
+ /* Disable interrupts */\r
+ HAL_set_8bit_reg( this_uart->base_address, IER, irq_mask );\r
+ }\r
+}\r
+\r
+/***************************************************************************//**\r
+ * UART_16550_set_rxstatus_handler.\r
+ * See core_16550.h for details of how to use this function.\r
+ */\r
+void\r
+UART_16550_set_rxstatus_handler\r
+(\r
+ uart_16550_instance_t * this_uart,\r
+ uart_16550_irq_handler_t handler\r
+)\r
+{\r
+ HAL_ASSERT( this_uart != NULL_INSTANCE )\r
+ HAL_ASSERT( handler != INVALID_IRQ_HANDLER)\r
+\r
+ if( ( this_uart != NULL_INSTANCE ) &&\r
+ ( handler != INVALID_IRQ_HANDLER) )\r
+ {\r
+ this_uart->linests_handler = handler;\r
+ /* Enable receiver line status interrupt. */\r
+ HAL_set_8bit_reg_field( this_uart->base_address, IER_ELSI, ENABLE );\r
+ }\r
+}\r
+\r
+/***************************************************************************//**\r
+ * UART_16550_set_tx_handler.\r
+ * See core_16550.h for details of how to use this function.\r
+ */\r
+void\r
+UART_16550_set_tx_handler\r
+(\r
+ uart_16550_instance_t * this_uart,\r
+ uart_16550_irq_handler_t handler\r
+)\r
+{\r
+ HAL_ASSERT( this_uart != NULL_INSTANCE )\r
+ HAL_ASSERT( handler != INVALID_IRQ_HANDLER)\r
+\r
+ if( ( this_uart != NULL_INSTANCE ) &&\r
+ ( handler != INVALID_IRQ_HANDLER) )\r
+ {\r
+ this_uart->tx_handler = handler;\r
+\r
+ /* Make TX buffer info invalid */\r
+ this_uart->tx_buffer = NULL_BUFF;\r
+ this_uart->tx_buff_size = 0U;\r
+\r
+ /* Enable transmitter holding register Empty interrupt. */\r
+ HAL_set_8bit_reg_field( this_uart->base_address, IER_ETBEI, ENABLE );\r
+ }\r
+}\r
+\r
+/***************************************************************************//**\r
+ * UART_16550_set_modemstatus_handler.\r
+ * See core_16550.h for details of how to use this function.\r
+ */\r
+void\r
+UART_16550_set_modemstatus_handler\r
+(\r
+ uart_16550_instance_t * this_uart,\r
+ uart_16550_irq_handler_t handler\r
+)\r
+{\r
+ HAL_ASSERT( this_uart != NULL_INSTANCE )\r
+ HAL_ASSERT( handler != INVALID_IRQ_HANDLER)\r
+\r
+ if( ( this_uart != NULL_INSTANCE ) &&\r
+ ( handler != INVALID_IRQ_HANDLER) )\r
+ {\r
+ this_uart->modemsts_handler = handler;\r
+ /* Enable modem status interrupt. */\r
+ HAL_set_8bit_reg_field( this_uart->base_address, IER_EDSSI, ENABLE );\r
+ }\r
+}\r
+\r
+/***************************************************************************//**\r
+ * UART_16550_fill_tx_fifo.\r
+ * See core_16550.h for details of how to use this function.\r
+ */\r
+size_t\r
+UART_16550_fill_tx_fifo\r
+(\r
+ uart_16550_instance_t * this_uart,\r
+ const uint8_t * tx_buffer,\r
+ size_t tx_size\r
+)\r
+{\r
+ uint8_t status;\r
+ size_t size_sent = 0U;\r
+\r
+ HAL_ASSERT( this_uart != NULL_INSTANCE )\r
+ HAL_ASSERT( tx_buffer != NULL_BUFF )\r
+ HAL_ASSERT( tx_size > 0U )\r
+\r
+ /* Fill the UART's Tx FIFO until the FIFO is full or the complete input\r
+ * buffer has been written. */\r
+ if( (this_uart != NULL_INSTANCE) &&\r
+ (tx_buffer != NULL_BUFF) &&\r
+ (tx_size > 0U) )\r
+ {\r
+ /* Read the Line Status Register and update the sticky record. */\r
+ status = HAL_get_8bit_reg( this_uart->base_address, LSR );\r
+ this_uart->status |= status;\r
+\r
+ /* Check if TX FIFO is empty. */\r
+ if( status & LSR_THRE_MASK )\r
+ {\r
+ uint32_t fill_size = TX_FIFO_SIZE;\r
+\r
+ /* Calculate the number of bytes to transmit. */\r
+ if ( tx_size < TX_FIFO_SIZE )\r
+ {\r
+ fill_size = tx_size;\r
+ }\r
+\r
+ /* Fill the TX FIFO with the calculated the number of bytes. */\r
+ for ( size_sent = 0U; size_sent < fill_size; ++size_sent )\r
+ {\r
+ /* Send next character in the buffer. */\r
+ HAL_set_8bit_reg( this_uart->base_address, THR,\r
+ (uint_fast8_t)tx_buffer[size_sent]);\r
+ }\r
+ }\r
+ }\r
+ return size_sent;\r
+}\r
+\r
+/***************************************************************************//**\r
+ * UART_16550_get_tx_status.\r
+ * See core_16550.h for details of how to use this function.\r
+ */\r
+uint8_t\r
+UART_16550_get_tx_status\r
+(\r
+ uart_16550_instance_t * this_uart\r
+)\r
+{\r
+ uint8_t status = UART_16550_TX_BUSY;\r
+ HAL_ASSERT( this_uart != NULL_INSTANCE );\r
+\r
+ if( ( this_uart != NULL_INSTANCE ) )\r
+ {\r
+ /* Read the Line Status Register and update the sticky record. */\r
+ status = HAL_get_8bit_reg( this_uart->base_address, LSR );\r
+ this_uart->status |= status;\r
+ /*\r
+ * Extract the transmit status bits from the UART's Line Status Register.\r
+ * Bit 5 - Transmitter Holding Register/FIFO Empty (THRE) status. (If = 1, TX FIFO is empty)\r
+ * Bit 6 - Transmitter Empty (TEMT) status. (If = 1, both TX FIFO and shift register are empty)\r
+ */\r
+ status &= ( LSR_THRE_MASK | LSR_TEMT_MASK );\r
+ }\r
+ return status;\r
+}\r
+\r
+\r
+#ifdef __cplusplus\r
+}\r
+#endif\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
--- /dev/null
+/*******************************************************************************\r
+ * (c) Copyright 2007-2015 Microsemi SoC Products Group. All rights reserved.\r
+ *\r
+ * This file contains the application programming interface for the Core16550\r
+ * bare metal driver.\r
+ *\r
+ * SVN $Revision: 7963 $\r
+ * SVN $Date: 2015-10-09 17:58:21 +0530 (Fri, 09 Oct 2015) $\r
+ */\r
+/*=========================================================================*//**\r
+ @mainpage Core16550 Bare Metal Driver.\r
+\r
+ @section intro_sec Introduction\r
+ The Core16550 is an implementation of the Universal Asynchronous\r
+ Receiver/Transmitter aimed at complete compliance to standard 16550 UART.\r
+ The Core16550 bare metal software driver is designed for use in systems\r
+ with no operating system.\r
+\r
+ The Core16550 driver provides functions for polled and interrupt driven\r
+ transmitting and receiving. It also provides functions for reading the\r
+ values from different status registers, enabling and disabling interrupts\r
+ at Core16550 level. The Core16550 driver is provided as C source code.\r
+\r
+ @section driver_configuration Driver Configuration\r
+ Your application software should configure the Core16550 driver through\r
+ calls to the UART_16550_init() function for each Core16550 instance in\r
+ the hardware design. The configuration parameters include the Core16550\r
+ hardware instance base address and other runtime parameters, such as baud\r
+ value, bit width, and parity.\r
+\r
+ No Core16550 hardware configuration parameters are needed by the driver,\r
+ apart from the Core16550 hardware instance base address. Hence, no\r
+ additional configuration files are required to use the driver.\r
+\r
+ @section theory_op Theory of Operation\r
+ The Core16550 software driver is designed to allow the control of multiple\r
+ instances of Core16550. Each instance of Core16550 in the hardware design\r
+ is associated with a single instance of the uart_16550_instance_t structure\r
+ in the software. You need to allocate memory for one unique\r
+ uart_16550_instance_t structure instance for each Core16550 hardware instance.\r
+ The contents of these data structures are initialized during calls to\r
+ function UART_16550_init(). A pointer to the structure is passed to\r
+ subsequent driver functions in order to identify the Core16550 hardware\r
+ instance you wish to perform the requested operation on.\r
+\r
+ Note: Do not attempt to directly manipulate the content of\r
+ uart_16550_instance_t structures. This structure is only intended to be\r
+ modified by the driver function.\r
+\r
+ Initialization\r
+ The Core16550 driver is initialized through a call to the UART_16550_init()\r
+ function. This function takes the UART\92s configuration as parameters.\r
+ The UART_16550_init() function must be called before any other Core16550\r
+ driver functions can be called.\r
+\r
+ Polled Transmission and Reception\r
+ The driver can be used to transmit and receive data once initialized. Polled\r
+ operations where the driver constantly polls the state of the UART registers\r
+ in order to control data transmit or data receive are performed using these\r
+ functions:\r
+ \95 UART_16550_polled_tx()\r
+ \95 UART_16550_polled_tx_string\r
+ \95 UART_16550_fill_tx_fifo()\r
+ \95 UART_16550_get_rx()\r
+\r
+ Data is transmitted using the UART_16550_polled_tx() function. This function\r
+ is blocking, meaning that it will only return once the data passed to the\r
+ function has been sent to the Core16550 hardware. Data received by the\r
+ Core16550 hardware can be read by the UART_16550_get_rx() function.\r
+\r
+ The UART_16550_polled_tx_string() function is provided to transmit a NULL (\91\0\92)\r
+ terminated string in polled mode. This function is blocking, meaning that it\r
+ will only return once the data passed to the function has been sent to the\r
+ Core16550 hardware.\r
+\r
+ The UART_16550_fill_tx_fifo() function fills the Core16550 hardware transmit\r
+ FIFO with data from a buffer passed as a parameter and returns the number of\r
+ bytes transferred to the FIFO. If the transmit FIFO is not empty when the\r
+ UART_16550_fill_tx_fifo() function is called it returns immediately without\r
+ transferring any data to the FIFO.\r
+\r
+ Interrupt Driven Operations\r
+ The driver can also transmit or receive data under interrupt control, freeing\r
+ your application to perform other tasks until an interrupt occurs indicating\r
+ that the driver\92s attention is required. Interrupt controlled UART operations\r
+ are performed using these functions:\r
+ \95 UART_16550_isr()\r
+ \95 UART_16550_irq_tx()\r
+ \95 UART_16550_tx_complete()\r
+ \95 UART_16550_set_tx_handler()\r
+ \95 UART_16550_set_rx_handler()\r
+ \95 UART_16550_set_rxstatus_handler()\r
+ \95 UART_16550_set_modemstatus_handler()\r
+ \95 UART_16550_enable_irq()\r
+ \95 UART_16550_disable_irq()\r
+\r
+ Interrupt Handlers\r
+ The UART_16550_isr() function is the top level interrupt handler function for\r
+ the Core16550 driver. You must call it from the system level\r
+ (CoreInterrupt and NVIC level) interrupt service routine (ISR) assigned to the\r
+ interrupt triggered by the Core16550 INTR signal. The UART_16550_isr() function\r
+ identifies the source of the Core16550 interrupt and calls the corresponding\r
+ handler function previously registered with the driver through calls to the\r
+ UART_16550_set_rx_handler(), UART_16550_set_tx_handler(),\r
+ UART_16550_set_rxstatus_handler(), and UART_16550_set_modemstatus_handler()\r
+ functions. You are responsible for creating these lower level interrupt handlers\r
+ as part of your application program and registering them with the driver.\r
+ The UART_16550_enable_irq() and UART_16550_disable_irq() functions are used to\r
+ enable or disable the received line status, received data available/character\r
+ timeout, transmit holding register empty and modem status interrupts at the\r
+ Core16550 level.\r
+\r
+ Transmitting Data\r
+ Interrupt-driven transmit is initiated by a call to UART_16550_irq_tx(),\r
+ specifying the block of data to transmit. Your application is then free to\r
+ perform other tasks and inquire later whether transmit has completed by calling\r
+ the UART_16550_tx_complete() function. The UART_16550_irq_tx() function enables\r
+ the UART\92s transmit holding register empty (THRE) interrupt and then, when the\r
+ interrupt goes active, the driver\92s default THRE interrupt handler transfers\r
+ the data block to the UART until the entire block is transmitted.\r
+\r
+ Note: You can use the UART_16550_set_tx_handler() function to assign an\r
+ alternative handler to the THRE interrupt. In this case, you must not use the\r
+ UART_16550_irq_tx() function to initiate the transmit, as this will re-assign\r
+ the driver\92s default THRE interrupt handler to the THRE interrupt. Instead,\r
+ your alternative THRE interrupt handler must include a call to the\r
+ UART_16550_fill_tx_fifo() function to transfer the data to the UART.\r
+\r
+ Receiving Data\r
+ Interrupt-driven receive is performed by first calling UART_16550_set_rx_handler()\r
+ to register a receive handler function that will be called by the driver whenever\r
+ receive data is available. You must provide this receive handler function which\r
+ must include a call to the UART_16550_get_rx() function to actually read the\r
+ received data.\r
+\r
+ UART Status\r
+ The function UART_16550_get_rx_status() is used to read the receiver error status.\r
+ This function returns the overrun, parity, framing, break, and FIFO error status\r
+ of the receiver.\r
+ The function UART_16550_get_tx_status() is used to read the transmitter status.\r
+ This function returns the transmit empty (TEMT) and transmit holding register\r
+ empty (THRE) status of the transmitter.\r
+ The function UART_16550_get_modem_status() is used to read the modem status flags.\r
+ This function returns the current value of the modem status register.\r
+\r
+ Loopback\r
+ The function UART_16550_set_loopback() is used to enable or disable loopback\r
+ between Tx and Rx lines internal to Core16550.\r
+*//*=========================================================================*/\r
+#ifndef __CORE_16550_H\r
+#define __CORE_16550_H 1\r
+\r
+#include "cpu_types.h"\r
+\r
+#ifdef __cplusplus\r
+extern "C" {\r
+#endif\r
+\r
+/***************************************************************************//**\r
+ * Receiver Error Status\r
+ * The following defines are used to determine the UART receiver error type.\r
+ * These bit mask constants are used with the return value of the\r
+ * UART_16550_get_rx_status() function to find out if any errors occurred\r
+ * while receiving data.\r
+ */\r
+#define UART_16550_NO_ERROR ( (uint8_t) 0x00 )\r
+#define UART_16550_OVERRUN_ERROR ( (uint8_t) 0x02 )\r
+#define UART_16550_PARITY_ERROR ( (uint8_t) 0x04 )\r
+#define UART_16550_FRAMING_ERROR ( (uint8_t) 0x08 )\r
+#define UART_16550_BREAK_ERROR ( (uint8_t) 0x10 )\r
+#define UART_16550_FIFO_ERROR ( (uint8_t) 0x80 )\r
+#define UART_16550_INVALID_PARAM ( (uint8_t) 0xFF )\r
+\r
+/***************************************************************************//**\r
+ * Modem Status\r
+ * The following defines are used to determine the modem status. These bit\r
+ * mask constants are used with the return value of the\r
+ * UART_16550_get_modem_status() function to find out the modem status of\r
+ * the UART.\r
+ */\r
+#define UART_16550_DCTS ( (uint8_t) 0x01 )\r
+#define UART_16550_DDSR ( (uint8_t) 0x02 )\r
+#define UART_16550_TERI ( (uint8_t) 0x04 )\r
+#define UART_16550_DDCD ( (uint8_t) 0x08 )\r
+#define UART_16550_CTS ( (uint8_t) 0x10 )\r
+#define UART_16550_DSR ( (uint8_t) 0x20 )\r
+#define UART_16550_RI ( (uint8_t) 0x40 )\r
+#define UART_16550_DCD ( (uint8_t) 0x80 )\r
+\r
+/***************************************************************************//**\r
+ * Transmitter Status\r
+ * The following definitions are used to determine the UART transmitter status.\r
+ * These bit mask constants are used with the return value of the\r
+ * UART_16550_get_tx_status() function to find out the status of the\r
+ * transmitter.\r
+ */\r
+#define UART_16550_TX_BUSY ( (uint8_t) 0x00 )\r
+#define UART_16550_THRE ( (uint8_t) 0x20 )\r
+#define UART_16550_TEMT ( (uint8_t) 0x40 )\r
+\r
+/***************************************************************************//**\r
+ * Core16550 Interrupts\r
+ * The following defines are used to enable and disable Core16550 interrupts.\r
+ * They are used to build the value of the irq_mask parameter for the\r
+ * UART_16550_enable_irq() and UART_16550_disable_irq() functions. A bitwise\r
+ * OR of these constants is used to enable or disable multiple interrupts.\r
+ */\r
+#define UART_16550_RBF_IRQ ( (uint8_t) 0x01 )\r
+#define UART_16550_TBE_IRQ ( (uint8_t) 0x02 )\r
+#define UART_16550_LS_IRQ ( (uint8_t) 0x04 )\r
+#define UART_16550_MS_IRQ ( (uint8_t) 0x08 )\r
+\r
+/***************************************************************************//**\r
+ * Data Width\r
+ * The following defines are used to build the value of the UART_16550_init()\r
+ * function line_config parameter.\r
+ */\r
+#define UART_16550_DATA_5_BITS ( (uint8_t) 0x00 )\r
+#define UART_16550_DATA_6_BITS ( (uint8_t) 0x01 )\r
+#define UART_16550_DATA_7_BITS ( (uint8_t) 0x02 )\r
+#define UART_16550_DATA_8_BITS ( (uint8_t) 0x03 )\r
+\r
+/***************************************************************************//**\r
+ * Parity Control\r
+ * The following defines are used to build the value of the UART_16550_init()\r
+ * function line_config parameter.\r
+ */\r
+#define UART_16550_NO_PARITY ( (uint8_t) 0x00 )\r
+#define UART_16550_ODD_PARITY ( (uint8_t) 0x08 )\r
+#define UART_16550_EVEN_PARITY ( (uint8_t) 0x18 )\r
+#define UART_16550_STICK_PARITY_1 ( (uint8_t) 0x28 )\r
+#define UART_16550_STICK_PARITY_0 ( (uint8_t) 0x38 )\r
+\r
+/***************************************************************************//**\r
+ * Number of Stop Bits\r
+ * The following defines are used to build the value of the UART_16550_init()\r
+ * function line_config parameter.\r
+ */\r
+#define UART_16550_ONE_STOP_BIT ( (uint8_t) 0x00 )\r
+/*only when data bits is 5*/\r
+#define UART_16550_ONEHALF_STOP_BIT ( (uint8_t) 0x04 )\r
+/*only when data bits is not 5*/\r
+#define UART_16550_TWO_STOP_BITS ( (uint8_t) 0x04 )\r
+\r
+/***************************************************************************//**\r
+ This enumeration specifies the receiver FIFO trigger level. This is the number\r
+ of bytes that must be received before the UART generates a receive data\r
+ available interrupt. It provides the allowed values for the\r
+ UART_16550_set_rx_handler() function\92s trigger_level parameter.\r
+ */\r
+typedef enum {\r
+ UART_16550_FIFO_SINGLE_BYTE = 0,\r
+ UART_16550_FIFO_FOUR_BYTES = 1,\r
+ UART_16550_FIFO_EIGHT_BYTES = 2,\r
+ UART_16550_FIFO_FOURTEEN_BYTES = 3,\r
+ UART_16550_FIFO_INVALID_TRIG_LEVEL\r
+} uart_16550_rx_trig_level_t;\r
+\r
+/***************************************************************************//**\r
+ This enumeration specifies the Loopback configuration of the UART. It provides\r
+ the allowed values for the UART_16550_set_loopback() function\92s loopback\r
+ parameter.\r
+ */\r
+typedef enum {\r
+ UART_16550_LOOPBACK_OFF = 0,\r
+ UART_16550_LOOPBACK_ON = 1,\r
+ UART_16550_INVALID_LOOPBACK\r
+} uart_16550_loopback_t;\r
+\r
+/***************************************************************************//**\r
+ This is type definition for Core16550 instance. You need to create and\r
+ maintain a record of this type. This holds all data regarding the Core16550\r
+ instance.\r
+ */\r
+typedef struct uart_16550_instance uart_16550_instance_t;\r
+\r
+/***************************************************************************//**\r
+ This typedef specifies the function prototype for Core16550 interrupt handlers.\r
+ All interrupt handlers registered with the Core16550 driver must be of this\r
+ type. The interrupt handlers are registered with the driver through the\r
+ UART_16550_set_rx_handler(), UART_16550_set_tx_handler(),\r
+ UART_16550_set_rxstatus_handler(), and UART_16550_set_modemstatus_handler()\r
+ functions.\r
+\r
+ The this_uart parameter is a pointer to a uart_16550_instance_t structure that\r
+ holds all data regarding this instance of the Core16550.\r
+ */\r
+typedef void (*uart_16550_irq_handler_t)(uart_16550_instance_t * this_uart);\r
+\r
+/***************************************************************************//**\r
+ uart_16550_instance.\r
+ This structure is used to identify the various Core16550 hardware instances\r
+ in your system. Your application software should declare one instance of this\r
+ structure for each instance of Core16550 in your system. The function\r
+ UART_16550_init() initializes this structure. A pointer to an initialized\r
+ instance of the structure should be passed as the first parameter to the\r
+ Core16550 driver functions, to identify which Core16550 hardware instance\r
+ should perform the requested operation.\r
+ */\r
+struct uart_16550_instance{\r
+ /* Core16550 instance base address: */\r
+ addr_t base_address;\r
+ /* Accumulated status: */\r
+ uint8_t status;\r
+\r
+ /* transmit related info: */\r
+ const uint8_t* tx_buffer;\r
+ uint32_t tx_buff_size;\r
+ uint32_t tx_idx;\r
+\r
+ /* line status (OE, PE, FE & BI) interrupt handler:*/\r
+ uart_16550_irq_handler_t linests_handler;\r
+ /* receive interrupt handler:*/\r
+ uart_16550_irq_handler_t rx_handler;\r
+ /* transmitter holding register interrupt handler:*/\r
+ uart_16550_irq_handler_t tx_handler;\r
+ /* modem status interrupt handler:*/\r
+ uart_16550_irq_handler_t modemsts_handler;\r
+};\r
+\r
+/***************************************************************************//**\r
+ * The UART_16550_init() function initializes the driver\92s data structures and\r
+ * the Core16550 hardware with the configuration passed as parameters.. The\r
+ * configuration parameters are the baud_value used to generate the baud rate,\r
+ * and the line_config used to specify the line configuration (bit length,\r
+ * stop bits and parity).\r
+ *\r
+ * @param this_uart The this_uart parameter is a pointer to a\r
+ * uart_16550_instance_t structure that holds all data\r
+ * regarding this instance of the Core16550. This pointer\r
+ * is used to identify the target Core16550 hardware\r
+ * instance in subsequent calls to the Core16550 driver\r
+ * functions.\r
+ * @param base_addr The base_address parameter is the base address in the\r
+ * processor's memory map for the registers of the\r
+ * Core16550 instance being initialized.\r
+ * @param baud_value The baud_value parameter is used to select the baud rate\r
+ * for the UART. The baud value is calculated from the\r
+ * frequency of the system clock in Hertz and the desired\r
+ * baud rate using the following equation:\r
+ *\r
+ * baud_value = (clock /(baud_rate * 16))\r
+ *\r
+ * The baud_value parameter must be a value in the range 0\r
+ * to 65535 (or 0x0000 to 0xFFFF).\r
+ * @param line_config This parameter is the line configuration specifying the\r
+ * bit length, number of stop bits and parity settings. This\r
+ * is a bitwise OR of one value from each of the following\r
+ * groups of allowed values:\r
+ * \95 Data lengths:\r
+ * UART_16550_DATA_5_BITS\r
+ * UART_16550_DATA_6_BITS\r
+ * UART_16550_DATA_7_BITS\r
+ * UART_16550_DATA_8_BITS\r
+ * \95 Parity types:\r
+ * UART_16550_NO_PARITY\r
+ * UART_16550_EVEN_PARITY\r
+ * UART_16550_ODD_PARITY\r
+ * UART_16550_STICK_PARITY_0\r
+ * UART_16550_STICK_PARITY_1\r
+ * \95 Number of stop bits:\r
+ * UART_16550_ONE_STOP_BIT\r
+ * UART_16550_ONEHALF_STOP_BIT\r
+ * UART_16550_TWO_STOP_BITS\r
+ * @return This function does not return a value.\r
+ *\r
+ * Example:\r
+ * @code\r
+ * #define UART_16550_BASE_ADDR 0x2A000000\r
+ * #define BAUD_VALUE_57600 26\r
+ *\r
+ * uart_16550_instance_t g_uart;\r
+ *\r
+ * UART_16550_init( &g_uart, UART_16550_BASE_ADDR, BAUD_VALUE_57600,\r
+ * (UART_16550_DATA_8_BITS |\r
+ * UART_16550_EVEN_PARITY |\r
+ * UART_16550_ONE_STOP_BIT) );\r
+ * @endcode\r
+ */\r
+void\r
+UART_16550_init\r
+(\r
+ uart_16550_instance_t* this_uart,\r
+ addr_t base_addr,\r
+ uint16_t baud_value,\r
+ uint8_t line_config\r
+);\r
+\r
+/***************************************************************************//**\r
+ * The UART_16550_polled_tx() function is used to transmit data. It transfers\r
+ * the contents of the transmitter data buffer, passed as a function parameter,\r
+ * into the UART's hardware transmitter FIFO. It returns when the full content\r
+ * of the transmitter data buffer has been transferred to the UART's transmitter\r
+ * FIFO. It is safe to release or reuse the memory used as the transmitter data\r
+ * buffer once this function returns.\r
+ *\r
+ * Note: This function reads the UART\92s line status register (LSR) to poll\r
+ * for the active state of the transmitter holding register empty (THRE) bit\r
+ * before transferring data from the data buffer to the transmitter FIFO. It\r
+ * transfers data to the transmitter FIFO in blocks of 16 bytes or less and\r
+ * allows the FIFO to empty before transferring the next block of data.\r
+ *\r
+ * Note: The actual transmission over the serial connection will still be in\r
+ * progress when this function returns. Use the UART_16550_get_tx_status()\r
+ * function if you need to know when the transmitter is empty.\r
+ *\r
+ * @param this_uart The this_uart parameter is a pointer to a\r
+ * uart_16550_instance_t structure that holds all\r
+ * data regarding this instance of the Core16550.\r
+ * @param pbuff The pbuff parameter is a pointer to a buffer containing\r
+ * the data to be transmitted.\r
+ * @param tx_size The tx_size parameter is the size, in bytes, of the\r
+ * data to be transmitted.\r
+ * @return This function does not return a value.\r
+ *\r
+ * Example:\r
+ * @code\r
+ * uint8_t testmsg1[] = {"\n\r\n\r\n\rUART_16550_polled_tx() test message 1"};\r
+ * UART_16550_polled_tx(&g_uart,(const uint8_t *)testmsg1,sizeof(testmsg1));\r
+ * @endcode\r
+ */\r
+void\r
+UART_16550_polled_tx\r
+(\r
+ uart_16550_instance_t * this_uart,\r
+ const uint8_t * pbuff,\r
+ uint32_t tx_size\r
+);\r
+/***************************************************************************//**\r
+ * The UART_16550_polled_tx_string() function is used to transmit a NULL ('\0')\r
+ * terminated string. It transfers the text string, from the buffer starting at\r
+ * the address pointed to by p_sz_string, into the UART\92s hardware transmitter\r
+ * FIFO. It returns when the complete string has been transferred to the UART's\r
+ * transmit FIFO. It is safe to release or reuse the memory used as the string\r
+ * buffer once this function returns.\r
+ *\r
+ * Note: This function reads the UART\92s line status register (LSR) to poll\r
+ * for the active state of the transmitter holding register empty (THRE) bit\r
+ * before transferring data from the data buffer to the transmitter FIFO. It\r
+ * transfers data to the transmitter FIFO in blocks of 16 bytes or less and\r
+ * allows the FIFO to empty before transferring the next block of data.\r
+ *\r
+ * Note: The actual transmission over the serial connection will still be\r
+ * in progress when this function returns. Use the UART_16550_get_tx_status()\r
+ * function if you need to know when the transmitter is empty.\r
+ *\r
+ * @param this_uart The this_uart parameter is a pointer to a\r
+ * uart_16550_instance_t structure that holds all data\r
+ * regarding this instance of the Core16550.\r
+ * @param p_sz_string The p_sz_string parameter is a pointer to a buffer\r
+ * containing the NULL ('\0') terminated string to be\r
+ * transmitted.\r
+ * @return This function does not return a value.\r
+ *\r
+ * Example:\r
+ * @code\r
+ * uint8_t testmsg1[] = {"\r\n\r\nUART_16550_polled_tx_string() test message 1\0"};\r
+ * UART_16550_polled_tx_string(&g_uart,(const uint8_t *)testmsg1);\r
+ * @endcode\r
+ */\r
+void\r
+UART_16550_polled_tx_string\r
+(\r
+ uart_16550_instance_t * this_uart,\r
+ const uint8_t * p_sz_string\r
+);\r
+\r
+/***************************************************************************//**\r
+ * The UART_16550_irq_tx() function is used to initiate an interrupt driven\r
+ * transmit. It returns immediately after making a note of the transmit buffer\r
+ * location and enabling the transmitter holding register empty (THRE) interrupt\r
+ * at the Core16550 level. This function takes a pointer via the pbuff parameter\r
+ * to a memory buffer containing the data to transmit. The memory buffer\r
+ * specified through this pointer must remain allocated and contain the data to\r
+ * transmit until the transmit completion has been detected through calls to\r
+ * function UART_16550_tx_complete().The actual transmission over the serial\r
+ * connection is still in progress until calls to the UART_16550_tx_complete()\r
+ * function indicate transmit completion.\r
+ *\r
+ * Note: It is your responsibility to call UART_16550_isr(), the driver\92s\r
+ * top level interrupt handler function, from the system level (CoreInterrupt\r
+ * and NVIC level) interrupt handler assigned to the interrupt triggered by the\r
+ * Core16550 INTR signal. You must do this before using the UART_16550_irq_tx()\r
+ * function.\r
+ *\r
+ * Note: It is also your responsibility to enable the system level\r
+ * (CoreInterrupt and NVIC level) interrupt connected to the Core16550 INTR\r
+ * interrupt signal.\r
+ *\r
+ * Note: The UART_16550_irq_tx() function assigns an internal default transmit\r
+ * interrupt handler function to the UART\92s THRE interrupt. This interrupt handler\r
+ * overrides any custom interrupt handler that you may have previously registered\r
+ * using the UART_16550_set_tx_handler() function.\r
+ *\r
+ * Note: The UART_16550_irq_tx() function\92s default transmit interrupt handler\r
+ * disables the UART\92s THRE interrupt when all of the data has been transferred\r
+ * to the UART's transmit FIFO.\r
+ *\r
+ * @param this_uart The this_uart parameter is a pointer to a\r
+ * uart_16550_instance_t structure that holds all data\r
+ * regarding this instance of the Core16550.\r
+ * @param pbuff The pbuff parameter is a pointer to a buffer containing\r
+ * the data to be transmitted.\r
+ * @param tx_size The tx_size parameter specifies the size, in bytes, of\r
+ * the data to be transmitted.\r
+ * @return This function does not return a value.\r
+ *\r
+ * Example:\r
+ * @code\r
+ * uint8_t tx_buff[10] = "abcdefghi";\r
+ *\r
+ * UART_16550_irq_tx( &g_uart, tx_buff, sizeof(tx_buff));\r
+ * while ( 0 == UART_16550_tx_complete( &g_uart ) )\r
+ * { ; }\r
+ * @endcode\r
+ */\r
+void\r
+UART_16550_irq_tx\r
+(\r
+ uart_16550_instance_t * this_uart,\r
+ const uint8_t * pbuff,\r
+ uint32_t tx_size\r
+);\r
+\r
+/***************************************************************************//**\r
+ * The UART_16550_tx_complete() function is used to find out if the interrupt\r
+ * driven transmit previously initiated through a call to UART_16550_irq_tx()\r
+ * is complete. This function is typically used to find out when it is safe\r
+ * to reuse or release the memory buffer holding the transmit data.\r
+ *\r
+ * Note: The transfer of all of the data from the memory buffer to the UART\92s\r
+ * transmit FIFO and the actual transmission over the serial connection are both\r
+ * complete when a call to the UART_16550_tx_complete() function indicate\r
+ * transmit completion.\r
+ *\r
+ * @param this_uart The this_uart parameter is a pointer to a\r
+ * uart_16550_instance_t structure that holds all data\r
+ * regarding this instance of the Core16550.\r
+ * @return This function returns a non-zero value if transmit has\r
+ * completed, otherwise it returns zero.\r
+ * Example:\r
+ * See the UART_16550_irq_tx() function for an example that uses the\r
+ * UART_16550_tx_complete() function.\r
+ */\r
+int8_t\r
+UART_16550_tx_complete\r
+(\r
+ uart_16550_instance_t * this_uart\r
+);\r
+\r
+/***************************************************************************//**\r
+ * The UART_16550_get_rx() function reads the content of the Core16550\r
+ * receiver\92s FIFO and stores it in the receive buffer that is passed via the\r
+ * rx_buff function parameter. It copies either the full contents of the FIFO\r
+ * into the receive buffer, or just enough data from the FIFO to fill the receive\r
+ * buffer, dependent upon the size of the receive buffer passed by the buff_size\r
+ * parameter. The UART_16550_get_rx() function returns the number of bytes copied\r
+ * into the receive buffer .This function is non-blocking and will return 0\r
+ * immediately if no data has been received.\r
+ *\r
+ * Note: The UART_16550_get_rx() function reads and accumulates the receiver\r
+ * status of the Core16550 instance before reading each byte from the receiver's\r
+ * data register/FIFO. This allows the driver to maintain a sticky record of any\r
+ * receiver errors that occur as the UART receives each data byte; receiver errors\r
+ * would otherwise be lost after each read from the receiver's data register. A call\r
+ * to the UART_16550_get_rx_status() function returns any receiver errors accumulated\r
+ * during the execution of the UART_16550_get_rx() function.\r
+ *\r
+ * Note: If you need to read the error status for each byte received, set the\r
+ * buff_size to 1 and read the receive line error status for each byte using the\r
+ * UART_16550_get_rx_status() function.\r
+ * The UART_16550_get_rx() function can be used in polled mode, where it is called\r
+ * at regular intervals to find out if any data has been received, or in interrupt\r
+ * driven-mode, where it is called as part of a receive handler that is called by\r
+ * the driver as a result of data being received.\r
+ *\r
+ * Note: In interrupt driven mode you should call the UART_16550_get_rx()\r
+ * function as part of the receive handler function that you register with the\r
+ * Core16550 driver through a call to UART_16550_set_rx_handler().\r
+ *\r
+ * @param this_uart The this_uart parameter is a pointer to a\r
+ * uart_16550_instance_t structure that holds all data\r
+ * regarding this instance of the Core16550.\r
+ * @param rx_buff The rx_buff parameter is a pointer to a memory buffer\r
+ * where the received data is copied.\r
+ * @param buff_size The buff_size parameter is the size of the receive\r
+ * buffer in bytes.\r
+ * @return This function returns the number of bytes copied into\r
+ * the receive buffer.\r
+ * Example:\r
+ * @code\r
+ * #define MAX_RX_DATA_SIZE 256\r
+ *\r
+ * uint8_t rx_data[MAX_RX_DATA_SIZE];\r
+ * uint8_t rx_size = 0;\r
+ *\r
+ * rx_size = UART_16550_get_rx( &g_uart, rx_data, sizeof(rx_data) );\r
+ * @endcode\r
+ */\r
+size_t\r
+UART_16550_get_rx\r
+(\r
+ uart_16550_instance_t * this_uart,\r
+ uint8_t * rx_buff,\r
+ size_t buff_size\r
+);\r
+\r
+/***************************************************************************//**\r
+ * The UART_16550_isr() function is the top level interrupt handler function for\r
+ * the Core16550 driver. You must call UART_16550_isr() from the system level\r
+ * (CoreInterrupt and NVIC level) interrupt handler assigned to the interrupt\r
+ * triggered by the Core16550 INTR signal. Your system level interrupt handler\r
+ * must also clear the system level interrupt triggered by the Core16550 INTR\r
+ * signal before returning, to prevent a re-assertion of the same interrupt.\r
+ *\r
+ * Note: This function supports all types of interrupt triggered by Core16550.\r
+ * It is not a complete interrupt handler by itself; rather, it is a top level\r
+ * wrapper that abstracts Core16550 interrupt handling by calling lower level\r
+ * handler functions specific to each type of Core16550 interrupt. You must\r
+ * create the lower level handler functions to suit your application and\r
+ * register them with the driver through calls to the UART_16550_set_rx_handler(),\r
+ * UART_16550_set_tx_handler(), UART_16550_set_rxstatus_handler() and\r
+ * UART_16550_set_modemstatus_handler() functions.\r
+ *\r
+ * @param this_uart The this_uart parameter is a pointer to a\r
+ * uart_16550_instance_t structure that holds all data\r
+ * regarding this instance of the Core16550.\r
+ *\r
+ * @return This function does not return a value.\r
+ *\r
+ * Example:\r
+ * @code\r
+ * void CIC_irq1_handler(void)\r
+ * {\r
+ * UART_16550_isr( &g_uart );\r
+ * }\r
+ * @endcode\r
+ */\r
+void\r
+UART_16550_isr\r
+(\r
+ uart_16550_instance_t * this_uart\r
+);\r
+\r
+/***************************************************************************//**\r
+ * The UART_16550_set_rx_handler() function is used to register a receive handler\r
+ * function that is called by the driver when a UART receive data available (RDA)\r
+ * interrupt occurs. The UART_16550_set_rx_handler() function also enables the\r
+ * RDA interrupt at the Core16550 level. You must create and register the receive\r
+ * handler function to suit your application and it must include a call to the\r
+ * UART_16550_get_rx() function to actually read the received data.\r
+ *\r
+ * Note: The driver\92s top level interrupt handler function UART_16550_isr()\r
+ * will call your receive handler function in response to an RDA interrupt from\r
+ * the Core16550.\r
+ *\r
+ * Note: You can disable the RDA interrupt once the data is received by calling\r
+ * the UART_16550_disable_irq() function. This is your choice and is dependent\r
+ * upon your application.\r
+ *\r
+ * @param this_uart The this_uart parameter is a pointer to a\r
+ * uart_16550_instance_t structure that holds all data\r
+ * regarding this instance of the Core16550.\r
+ * @param handler The handler parameter is a pointer to a receive interrupt\r
+ * handler function provided by your application that will be\r
+ * called as a result of a UART RDA interrupt. This handler\r
+ * function must be of type uart_16550_irq_handler_t.\r
+ * @param trigger_level The trigger_level parameter is the receive FIFO\r
+ * trigger level. This specifies the number of bytes that\r
+ * must be received before the UART triggers an RDA\r
+ * interrupt.\r
+ * @return This function does not return a value.\r
+ *\r
+ * Example:\r
+ * @code\r
+ * #include "core_16550.h"\r
+ *\r
+ * #define RX_BUFF_SIZE 64\r
+ * #define UART_57600_BAUD 26\r
+ *\r
+ * uint8_t g_rx_buff[RX_BUFF_SIZE];\r
+ * uart_16550_instance_t g_uart;\r
+ * void uart_rx_handler( uart_16550_instance_t * this_uart )\r
+ * {\r
+ * UART_16550_get_rx( this_uart, g_rx_buff, RX_BUFF_SIZE );\r
+ * }\r
+ *\r
+ * int main(void)\r
+ * {\r
+ * UART_16550_init( &g_uart, UART_57600_BAUD,\r
+ * ( UART_16550_DATA_8_BITS | UART_16550_NO_PARITY ) );\r
+ * UART_16550_set_rx_handler( &g_uart, uart_rx_handler,\r
+ * UART_16550_FIFO_SINGLE_BYTE);\r
+ * while ( 1 )\r
+ * {\r
+ * ;\r
+ * }\r
+ * return(0);\r
+ * }\r
+ * @endcode\r
+ */\r
+void\r
+UART_16550_set_rx_handler\r
+(\r
+ uart_16550_instance_t * this_uart,\r
+ uart_16550_irq_handler_t handler,\r
+ uart_16550_rx_trig_level_t trigger_level\r
+);\r
+\r
+/***************************************************************************//**\r
+ * The UART_16550_set_loopback() function is used to locally loopback the Tx\r
+ * and Rx lines of a Core16550 UART.\r
+ *\r
+ * @param this_uart The this_uart parameter is a pointer to a\r
+ * uart_16550_instance_t structure that holds all data\r
+ * regarding this instance of the Core16550.\r
+ * @param loopback The loopback parameter indicates whether or not the\r
+ * UART's transmit and receive lines should be looped back.\r
+ * Allowed values are as follows:\r
+ * \95 UART_16550_LOOPBACK_ON\r
+ * \95 UART_16550_LOOPBACK_OFF\r
+ * @return This function does not return a value.\r
+ *\r
+ * Example:\r
+ * @code\r
+ * #include "core_16550.h"\r
+ *\r
+ * #define UART_57600_BAUD 26\r
+ * #define DATA_SIZE 4\r
+ *\r
+ * uart_16550_instance_t g_uart;\r
+ *\r
+ * int main(void)\r
+ * {\r
+ * uint8_t txbuf[DATA_SIZE] = "abc";\r
+ * uint8_t rxbuf[DATA_SIZE];\r
+ * UART_16550_init( &g_uart, UART_57600_BAUD,\r
+ * ( UART_16550_DATA_8_BITS | UART_16550_NO_PARITY |\r
+ * UART_16550_ONE_STOP_BIT) );\r
+ * UART_16550_set_loopback( &g_uart, UART_16550_LOOPBACK_ON );\r
+ *\r
+ * while(1)\r
+ * {\r
+ * UART_16550_polled_tx( &g_uart, txbuf, DATA_SIZE);\r
+ * delay(100);\r
+ * UART_16550_get_rx( &g_uart, rxbuf, DATA_SIZE);\r
+ * }\r
+ * }\r
+ * @endcode\r
+ */\r
+void\r
+UART_16550_set_loopback\r
+(\r
+ uart_16550_instance_t * this_uart,\r
+ uart_16550_loopback_t loopback\r
+);\r
+\r
+/***************************************************************************//**\r
+ * The UART_16550_get_rx_status() function returns the receiver error status of\r
+ * the Core16550 instance. It reads both the current error status of the receiver\r
+ * from the UART\92s line status register (LSR) and the accumulated error status\r
+ * from preceding calls to the UART_16550_get_rx() function, and it combines\r
+ * them using a bitwise OR. It returns the cumulative overrun, parity, framing,\r
+ * break and FIFO error status of the receiver, since the previous call to\r
+ * UART_16550_get_rx_status(), as an 8-bit encoded value.\r
+ *\r
+ * Note: The UART_16550_get_rx() function reads and accumulates the receiver\r
+ * status of the Core16550 instance before reading each byte from the receiver\92s\r
+ * data register/FIFO. The driver maintains a sticky record of the cumulative\r
+ * receiver error status, which persists after the UART_16550_get_rx() function\r
+ * returns. The UART_16550_get_rx_status() function clears the driver\92s sticky\r
+ * receiver error record before returning.\r
+ *\r
+ * Note: The driver\92s transmit functions also read the line status register\r
+ * (LSR) as part of their implementation. When the driver reads the LSR, the\r
+ * UART clears any active receiver error bits in the LSR. This could result in\r
+ * the driver losing receiver errors. To avoid any loss of receiver errors, the\r
+ * transmit functions also update the driver\92s sticky record of the cumulative\r
+ * receiver error status whenever they read the LSR.\r
+ *\r
+ * @param this_uart The this_uart parameter is a pointer to a\r
+ * uart_16550_instance_t structure that holds all data\r
+ * regarding this instance of the Core16550.\r
+ * @return This function returns the UART\92s receiver error status\r
+ * as an 8-bit unsigned integer. The returned value is 0\r
+ * if no receiver errors occurred. The driver provides a\r
+ * set of bit mask constants that should be compared with\r
+ * and/or used to mask the returned value to determine the\r
+ * receiver error status.\r
+ * When the return value is compared to the following bit\r
+ * masks, a non-zero result indicates that the\r
+ * corresponding error occurred:\r
+ * \95 UART_16550_OVERRUN_ERROR (bit mask = 0x02)\r
+ * \95 UART_16550_PARITY_ERROR (bit mask = 0x04)\r
+ * \95 UART_16550_FRAMING_ERROR (bit mask = 0x08)\r
+ * \95 UART_16550_BREAK_ERROR (bit mask = 0x10)\r
+ * \95 UART_16550_FIFO_ERROR (bit mask = 0x80)\r
+ * When the return value is compared to the following bit\r
+ * mask, a non-zero result indicates that no error occurred:\r
+ * \95 UART_16550_NO_ERROR (bit mask = 0x00)\r
+ * Upon unsuccessful execution, this function returns:\r
+ * \95 UART_16550_INVALID_PARAM (bit mask = 0xFF)\r
+ *\r
+ * Example:\r
+ * @code\r
+ * uart_16550_instance_t g_uart;\r
+ * uint8_t rx_data[MAX_RX_DATA_SIZE];\r
+ * uint8_t err_status;\r
+ *\r
+ * err_status = UART_16550_get_rx_status(&g_uart);\r
+ * if(UART_16550_NO_ERROR == err_status )\r
+ * {\r
+ * rx_size = UART_16550_get_rx( &g_uart, rx_data, MAX_RX_DATA_SIZE );\r
+ * }\r
+ * @endcode\r
+ */\r
+uint8_t\r
+UART_16550_get_rx_status\r
+(\r
+ uart_16550_instance_t * this_uart\r
+);\r
+/***************************************************************************//**\r
+ * The UART_16550_enable_irq() function enables the Core16550 interrupts\r
+ * specified by the irq_mask parameter. The irq_mask parameter identifies the\r
+ * Core16550 interrupts by bit position, as defined in the interrupt enable\r
+ * register (IER) of Core16550. The Core16550 interrupts and their identifying\r
+ * irq_mask bit positions are as follows:\r
+ * \95 Receive data available interrupt (RDA) (irq_mask bit 0)\r
+ * \95 Transmit holding register empty interrupt (THRE) (irq_mask bit 1)\r
+ * \95 Receiver line status interrupt (LS) (irq_mask bit 2)\r
+ * \95 Modem status interrupt (MS) (irq_mask bit 3)\r
+ * When an irq_mask bit position is set to 1, this function enables the\r
+ * corresponding Core16550 interrupt in the IER register. When an irq_mask\r
+ * bit position is set to 0, the corresponding interrupt\92s state remains\r
+ * unchanged in the IER register.\r
+ *\r
+ * @param this_uart The this_uart parameter is a pointer to a\r
+ * uart_16550_instance_t structure that holds all data\r
+ * regarding this instance of the Core16550.\r
+ * @param irq_mask The irq_mask parameter is used to select which of the\r
+ * Core16550\92s interrupts you want to enable. The allowed\r
+ * value for the irq_mask parameter is one of the\r
+ * following constants or a bitwise OR of more than one:\r
+ * \95 UART_16550_RBF_IRQ (bit mask = 0x01)\r
+ * \95 UART_16550_TBE_IRQ (bit mask = 0x02)\r
+ * \95 UART_16550_LS_IRQ (bit mask = 0x04)\r
+ * \95 UART_16550_MS_IRQ (bit mask = 0x08)\r
+ * @return This function does not return a value.\r
+ *\r
+ * Example:\r
+ * @code\r
+ * UART_16550_enable_irq( &g_uart,( UART_16550_RBF_IRQ | UART_16550_TBE_IRQ ) );\r
+ * @endcode\r
+ */\r
+void\r
+UART_16550_enable_irq\r
+(\r
+ uart_16550_instance_t * this_uart,\r
+ uint8_t irq_mask\r
+);\r
+\r
+/***************************************************************************//**\r
+ * The UART_16550_disable_irq() function disables the Core16550 interrupts\r
+ * specified by the irq_mask parameter. The irq_mask parameter identifies the\r
+ * Core16550 interrupts by bit position, as defined in the interrupt enable\r
+ * register (IER) of Core16550. The Core16550 interrupts and their identifying\r
+ * bit positions are as follows:\r
+ * \95 Receive data available interrupt (RDA) (irq_mask bit 0)\r
+ * \95 Transmit holding register empty interrupt (THRE) (irq_mask bit 1)\r
+ * \95 Receiver line status interrupt (LS) (irq_mask bit 2)\r
+ * \95 Modem status interrupt (MS) (irq_mask bit 3)\r
+ * When an irq_mask bit position is set to 1, this function disables the\r
+ * corresponding Core16550 interrupt in the IER register. When an irq_mask bit\r
+ * position is set to 0, the corresponding interrupt\92s state remains unchanged\r
+ * in the IER register.\r
+ *\r
+ * @param this_uart The this_uart parameter is a pointer to a\r
+ * uart_16550_instance_t structure that holds all data\r
+ * regarding this instance of the Core16550.\r
+ * @param irq_mask The irq_mask parameter is used to select which of the\r
+ * Core16550\92s interrupts you want to disable. The allowed\r
+ * value for the irq_mask parameter is one of the\r
+ * following constants or a bitwise OR of more than one:\r
+ * \95 UART_16550_RBF_IRQ (bit mask = 0x01)\r
+ * \95 UART_16550_TBE_IRQ (bit mask = 0x02)\r
+ * \95 UART_16550_LS_IRQ (bit mask = 0x04)\r
+ * \95 UART_16550_MS_IRQ (bit mask = 0x08)\r
+ * @return This function does not return a value.\r
+ *\r
+ * Example:\r
+ * @code\r
+ * UART_16550_disable_irq( &g_uart, ( UART_16550_RBF_IRQ | UART_16550_TBE_IRQ ) );\r
+ * @endcode\r
+ */\r
+void\r
+UART_16550_disable_irq\r
+(\r
+ uart_16550_instance_t * this_uart,\r
+ uint8_t irq_mask\r
+);\r
+\r
+/***************************************************************************//**\r
+ * The UART_16550_get_modem_status() function returns the modem status of the\r
+ * Core16550 instance. It reads the modem status register (MSR) and returns the\r
+ * 8 bit value. The bit encoding of the returned value is exactly the same as\r
+ * the definition of the bits in the MSR.\r
+ *\r
+ * @param this_uart The this_uart parameter is a pointer to a\r
+ * uart_16550_instance_t structure that holds all data\r
+ * regarding this instance of the Core16550.\r
+ * @return This function returns current state of the UART's MSR\r
+ * as an 8 bit unsigned integer. The driver provides the\r
+ * following set of bit mask constants that should be\r
+ * compared with and/or used to mask the returned value\r
+ * to determine the modem status:\r
+ * \95 UART_16550_DCTS (bit mask = 0x01)\r
+ * \95 UART_16550_DDSR (bit mask = 0x02)\r
+ * \95 UART_16550_TERI (bit mask = 0x04)\r
+ * \95 UART_16550_DDCD (bit mask = 0x08)\r
+ * \95 UART_16550_CTS (bit mask = 0x10)\r
+ * \95 UART_16550_DSR (bit mask = 0x20)\r
+ * \95 UART_16550_RI (bit mask = 0x40)\r
+ * \95 UART_16550_DCD (bit mask = 0x80)\r
+ * Example:\r
+ * @code\r
+ * void uart_modem_status_isr(uart_16550_instance_t * this_uart)\r
+ * {\r
+ * uint8_t status;\r
+ * status = UART_16550_get_modem_status( this_uart );\r
+ * if( status & UART_16550_DCTS )\r
+ * {\r
+ * uart_dcts_handler();\r
+ * }\r
+ * if( status & UART_16550_CTS )\r
+ * {\r
+ * uart_cts_handler();\r
+ * }\r
+ * }\r
+ * @endcode\r
+ */\r
+uint8_t\r
+UART_16550_get_modem_status\r
+(\r
+ uart_16550_instance_t * this_uart\r
+);\r
+\r
+/***************************************************************************//**\r
+ * The UART_16550_set_rxstatus_handler() function is used to register a receiver\r
+ * status handler function that is called by the driver when a UART receiver\r
+ * line status (RLS) interrupt occurs. The UART_16550_set_rxstatus_handler()\r
+ * function also enables the RLS interrupt at the Core16550 level. You must\r
+ * create and register the receiver status handler function to suit your\r
+ * application.\r
+ *\r
+ * Note: The driver\92s top level interrupt handler function UART_16550_isr()\r
+ * will call your receive status handler function in response to an RLS\r
+ * interrupt from the Core16550.\r
+ *\r
+ * Note: You can disable the RLS interrupt when required by calling the\r
+ * UART_16550_disable_irq() function. This is your choice and is dependent\r
+ * upon your application.\r
+ *\r
+ * @param this_uart The this_uart parameter is a pointer to a\r
+ * uart_16550_instance_t structure that holds all data\r
+ * regarding this instance of the Core16550.\r
+ * @param handler The handler parameter is a pointer to a receiver line\r
+ * status interrupt handler function provided by your\r
+ * application that will be called as a result of a\r
+ * UART RLS interrupt. This handler function must be\r
+ * of type uart_16550_irq_handler_t.\r
+ * Example:\r
+ * @code\r
+ * #include "core_16550.h"\r
+ *\r
+ * #define UART_57600_BAUD 26\r
+ *\r
+ * uart_16550_instance_t g_uart;\r
+ *\r
+ * void uart_rxsts_handler( uart_16550_instance_t * this_uart )\r
+ * {\r
+ * uint8_t status;\r
+ * status = UART_16550_get_rx_status( this_uart );\r
+ * if( status & UART_16550_OVERUN_ERROR )\r
+ * {\r
+ * discard_rx_data();\r
+ * }\r
+ * }\r
+ *\r
+ * int main(void)\r
+ * {\r
+ * UART_16550_init( &g_uart, UART_57600_BAUD,\r
+ * UART_16550_DATA_8_BITS | UART_16550_NO_PARITY |\r
+ * UART_16550_ONE_STOP_BIT );\r
+ * UART_16550_set_rxstatus_handler( &g_uart, uart_rxsts_handler );\r
+ *\r
+ * while ( 1 )\r
+ * {\r
+ * ;\r
+ * }\r
+ * return(0);\r
+ * }\r
+ * @endcode\r
+ */\r
+void\r
+UART_16550_set_rxstatus_handler\r
+(\r
+ uart_16550_instance_t * this_uart,\r
+ uart_16550_irq_handler_t handler\r
+);\r
+\r
+/***************************************************************************//**\r
+ * The UART_16550_set_tx_handler() function is used to register a transmit\r
+ * handler function that is called by the driver when a UART transmit holding\r
+ * register empty (THRE) interrupt occurs. The UART_16550_set_tx_handler()\r
+ * function also enables the THRE interrupt at the Core16550 level. You must\r
+ * create and register the transmit handler function to suit your application.\r
+ * You can use the UART_16550_fill_tx_fifo() function in your transmit handler\r
+ * function to write data to the transmitter.\r
+ *\r
+ * Note: The driver\92s top level interrupt handler function UART_16550_isr()\r
+ * will call your transmit handler function in response to an THRE interrupt\r
+ * from the Core16550.\r
+ *\r
+ * Note: You can disable the THRE interrupt when required by calling the\r
+ * UART_16550_disable_irq() function. This is your choice and is dependent\r
+ * upon your application.\r
+ *\r
+ * Note: The UART_16550_irq_tx() function does not use the transmit handler\r
+ * function that you register with the UART_16550_set_tx_handler() function.\r
+ * It uses its own internal THRE interrupt handler function that overrides any\r
+ * custom interrupt handler that you register using the\r
+ * UART_16550_set_tx_handler() function.\r
+ *\r
+ * @param this_uart The this_uart parameter is a pointer to a\r
+ * uart_16550_instance_t structure that holds all data\r
+ * regarding this instance of the Core16550.\r
+ * @param handler The handler parameter is a pointer to a transmitter\r
+ * interrupt handler function provided by your application,\r
+ * which will be called as a result of a UART THRE interrupt.\r
+ * This handler is of uart_16550_irq_handler_t type.\r
+ * @return This function does not return a value.\r
+ *\r
+ * Example:\r
+ * @code\r
+ * #include "core_16550.h"\r
+ *\r
+ * #define UART_57600_BAUD 26\r
+ *\r
+ * uart_16550_instance_t g_uart;\r
+ *\r
+ * uint8_t * g_tx_buffer;\r
+ * size_t g_tx_size = 0;\r
+ *\r
+ * void uart_tx_handler( uart_16550_instance_t * this_uart )\r
+ * {\r
+ * size_t size_in_fifo;\r
+ *\r
+ * size_in_fifo = UART_16550_fill_tx_fifo( this_uart,\r
+ * (const uint8_t *)g_tx_buffer,\r
+ * g_tx_size );\r
+ *\r
+ * if(size_in_fifo == g_tx_size)\r
+ * {\r
+ * g_tx_size = 0;\r
+ * UART_16550_disable_irq( this_uart, UART_16550_TBE_IRQ );\r
+ * }\r
+ * else\r
+ * {\r
+ * g_tx_buffer = &g_tx_buffer[size_in_fifo];\r
+ * g_tx_size = g_tx_size - size_in_fifo;\r
+ * }\r
+ * }\r
+ *\r
+ * int main(void)\r
+ * {\r
+ * uint8_t message[12] = "Hello world";\r
+ *\r
+ * UART_16550_init( &g_uart, UART_57600_BAUD,\r
+ * UART_16550_DATA_8_BITS | UART_16550_NO_PARITY |\r
+ * UART_16550_ONE_STOP_BIT );\r
+ *\r
+ * g_tx_buffer = message;\r
+ * g_tx_size = sizeof(message);\r
+ *\r
+ * UART_16550_set_tx_handler( &g_uart, uart_tx_handler);\r
+ *\r
+ * while ( 1 )\r
+ * {\r
+ * ;\r
+ * }\r
+ * return(0);\r
+ * }\r
+ *\r
+ * @endcode\r
+ */\r
+void\r
+UART_16550_set_tx_handler\r
+(\r
+ uart_16550_instance_t * this_uart,\r
+ uart_16550_irq_handler_t handler\r
+);\r
+\r
+/***************************************************************************//**\r
+ * The UART_16550_set_modemstatus_handler() function is used to register a\r
+ * modem status handler function that is called by the driver when a UART modem\r
+ * status (MS) interrupt occurs. The UART_16550_set_modemstatus_handler()\r
+ * function also enables the MS interrupt at the Core16550 level. You must\r
+ * create and register the modem status handler function to suit your\r
+ * application.\r
+ *\r
+ * Note: The driver\92s top level interrupt handler function UART_16550_isr()\r
+ * will call your receive status handler function in response to an MS interrupt\r
+ * from the Core16550.\r
+ *\r
+ * Note: You can disable the MS interrupt when required by calling the\r
+ * UART_16550_disable_irq() function. This is your choice and is dependent\r
+ * upon your application.\r
+ *\r
+ * @param this_uart The this_uart parameter is a pointer to a\r
+ * uart_16550_instance_t structure that holds all data\r
+ * regarding this instance of the Core16550.\r
+ * @param handler The handler parameter is a pointer to a modem status\r
+ * interrupt handler function provided by your application\r
+ * that will be called as a result of a UART MS interrupt.\r
+ * This handler function must be of type\r
+ * uart_16550_irq_handler_t.\r
+ * @return This function does not return a value.\r
+ *\r
+ * Example:\r
+ * @code\r
+ * #include "core_16550.h"\r
+ *\r
+ * #define UART_57600_BAUD 26\r
+ *\r
+ * uart_16550_instance_t g_uart;\r
+ *\r
+ * void uart_modem_handler( uart_16550_instance_t * this_uart )\r
+ * {\r
+ * uint8_t status;\r
+ * status = UART_16550_get_modem_status( this_uart );\r
+ * if( status & UART_16550_CTS )\r
+ * {\r
+ * uart_cts_handler();\r
+ * }\r
+ * }\r
+ *\r
+ * int main(void)\r
+ * {\r
+ * UART_16550_init( &g_uart, UART_57600_BAUD,\r
+ * UART_16550_DATA_8_BITS | UART_16550_NO_PARITY |\r
+ UART_16550_ONE_STOP_BIT);\r
+ * UART_16550_set_modemstatus_handler( &g_uart, uart_modem_handler);\r
+ *\r
+ * while ( 1 )\r
+ * {\r
+ * ;\r
+ * }\r
+ * return(0);\r
+ * }\r
+ * @endcode\r
+ */\r
+void\r
+UART_16550_set_modemstatus_handler\r
+(\r
+ uart_16550_instance_t * this_uart,\r
+ uart_16550_irq_handler_t handler\r
+);\r
+\r
+/***************************************************************************//**\r
+ * The UART_16550_fill_tx_fifo() function fills the UART's hardware transmitter\r
+ * FIFO with the data found in the transmitter buffer that is passed via the\r
+ * tx_buffer function parameter. If the transmitter FIFO is not empty when the\r
+ * function is called, the function returns immediately without transferring\r
+ * any data to the FIFO; otherwise, the function transfers data from the\r
+ * transmitter buffer to the FIFO until it is full or until the complete\r
+ * contents of the transmitter buffer have been copied into the FIFO. The\r
+ * function returns the number of bytes copied into the UART's transmitter FIFO.\r
+ *\r
+ * Note: This function reads the UART\92s line status register (LSR) to check\r
+ * for the active state of the transmitter holding register empty (THRE) bit\r
+ * before transferring data from the data buffer to the transmitter FIFO. If\r
+ * THRE is 0, the function returns immediately, without transferring any data\r
+ * to the FIFO. If THRE is 1, the function transfers up to 16 bytes of data to\r
+ * the FIFO and then returns.\r
+ *\r
+ * Note: The actual transmission over the serial connection will still be in\r
+ * progress when this function returns. Use the UART_16550_get_tx_status()\r
+ * function if you need to know when the transmitter is empty.\r
+ *\r
+ * @param this_uart The this_uart parameter is a pointer to a\r
+ * uart_16550_instance_t structure that holds all data\r
+ * regarding this instance of the Core16550.\r
+ * @param tx_buffer The tx_buffer parameter is a pointer to a buffer\r
+ * containing the data to be transmitted.\r
+ * @param tx_size The tx_size parameter is the size in bytes, of the data\r
+ * to be transmitted.\r
+ * @return This function returns the number of bytes copied\r
+ * into the UART's transmitter FIFO.\r
+ *\r
+ * Example:\r
+ * @code\r
+ * void send_using_interrupt(uint8_t * pbuff, size_t tx_size)\r
+ * {\r
+ * size_t size_in_fifo;\r
+ * size_in_fifo = UART_16550_fill_tx_fifo( &g_uart, pbuff, tx_size );\r
+ * }\r
+ * @endcode\r
+ */\r
+size_t\r
+UART_16550_fill_tx_fifo\r
+(\r
+ uart_16550_instance_t * this_uart,\r
+ const uint8_t * tx_buffer,\r
+ size_t tx_size\r
+);\r
+\r
+/***************************************************************************//**\r
+ * The UART_16550_get_tx_status() function returns the transmitter status of\r
+ * the Core16550 instance. It reads both the UART\92s line status register (LSR)\r
+ * and returns the status of the transmit holding register empty (THRE) and\r
+ * transmitter empty (TEMT) bits.\r
+ *\r
+ * @param this_uart The this_uart parameter is a pointer to a\r
+ * uart_16550_instance_t structure that holds all data\r
+ * regarding this instance of the Core16550.\r
+ * @return This function returns the UART\92s transmitter status\r
+ * as an 8-bit unsigned integer. The returned value is 0\r
+ * if the transmitter status bits are not set or the\r
+ * function execution failed. The driver provides a set\r
+ * of bit mask constants that should be compared with\r
+ * and/or used to mask the returned value to determine\r
+ * the transmitter status.\r
+ * When the return value is compared to the following\r
+ * bitmasks, a non-zero result indicates that the\r
+ * corresponding transmitter status bit is set:\r
+ * \95 UART_16550_THRE (bit mask = 0x20)\r
+ * \95 UART_16550_TEMT (bit mask = 0x40)\r
+ * When the return value is compared to the following\r
+ * bit mask, a non-zero result indicates that the\r
+ * transmitter is busy or the function execution failed.\r
+ * \95 UART_16550_TX_BUSY (bit mask = 0x00)\r
+ * Example:\r
+ * @code\r
+ * uint8_t tx_buff[10] = "abcdefghi";\r
+ *\r
+ * UART_16550_polled_tx( &g_uart, tx_buff, sizeof(tx_buff));\r
+ *\r
+ * while ( ! (UART_16550_TEMT & UART_16550_get_tx_status( &g_uart ) ) )\r
+ * {\r
+ * ;\r
+ * }\r
+ * @endcode\r
+ */\r
+uint8_t\r
+UART_16550_get_tx_status\r
+(\r
+ uart_16550_instance_t * this_uart\r
+);\r
+\r
+#ifdef __cplusplus\r
+}\r
+#endif\r
+\r
+#endif /* __CORE_16550_H */\r
--- /dev/null
+/*******************************************************************************\r
+ * (c) Copyright 2008-2015 Microsemi SoC Products Group. All rights reserved.\r
+ * \r
+ * CoreGPIO bare metal driver implementation.\r
+ *\r
+ * SVN $Revision: 7964 $\r
+ * SVN $Date: 2015-10-09 18:26:53 +0530 (Fri, 09 Oct 2015) $\r
+ */\r
+#include "core_gpio.h"\r
+#include "hal.h"\r
+#include "hal_assert.h"\r
+#include "coregpio_regs.h"\r
+\r
+/*-------------------------------------------------------------------------*//**\r
+ *\r
+ */\r
+#define GPIO_INT_ENABLE_MASK (uint32_t)0x00000008UL\r
+#define OUTPUT_BUFFER_ENABLE_MASK 0x00000004UL\r
+\r
+\r
+#define NB_OF_GPIO 32\r
+\r
+#define CLEAR_ALL_IRQ32 (uint32_t)0xFFFFFFFF\r
+#define CLEAR_ALL_IRQ16 (uint16_t)0xFFFF\r
+#define CLEAR_ALL_IRQ8 (uint8_t)0xFF\r
+\r
+/*-------------------------------------------------------------------------*//**\r
+ * GPIO_init()\r
+ * See "core_gpio.h" for details of how to use this function.\r
+ */\r
+void GPIO_init\r
+(\r
+ gpio_instance_t * this_gpio,\r
+ addr_t base_addr,\r
+ gpio_apb_width_t bus_width\r
+)\r
+{\r
+ uint8_t i = 0;\r
+ addr_t cfg_reg_addr = base_addr;\r
+ \r
+ this_gpio->base_addr = base_addr;\r
+ this_gpio->apb_bus_width = bus_width;\r
+ \r
+ /* Clear configuration. */\r
+ for( i = 0, cfg_reg_addr = base_addr; i < NB_OF_GPIO; ++i )\r
+ {\r
+ HW_set_8bit_reg( cfg_reg_addr, 0 );\r
+ cfg_reg_addr += 4;\r
+ }\r
+ /* Clear any pending interrupts */\r
+ switch( this_gpio->apb_bus_width )\r
+ {\r
+ case GPIO_APB_32_BITS_BUS:\r
+ HAL_set_32bit_reg( this_gpio->base_addr, IRQ, CLEAR_ALL_IRQ32 );\r
+ break;\r
+ \r
+ case GPIO_APB_16_BITS_BUS:\r
+ HAL_set_16bit_reg( this_gpio->base_addr, IRQ0, (uint16_t)CLEAR_ALL_IRQ16 );\r
+ HAL_set_16bit_reg( this_gpio->base_addr, IRQ1, (uint16_t)CLEAR_ALL_IRQ16 );\r
+ break;\r
+ \r
+ case GPIO_APB_8_BITS_BUS:\r
+ HAL_set_8bit_reg( this_gpio->base_addr, IRQ0, (uint8_t)CLEAR_ALL_IRQ8 );\r
+ HAL_set_8bit_reg( this_gpio->base_addr, IRQ1, (uint8_t)CLEAR_ALL_IRQ8 );\r
+ HAL_set_8bit_reg( this_gpio->base_addr, IRQ2, (uint8_t)CLEAR_ALL_IRQ8 );\r
+ HAL_set_8bit_reg( this_gpio->base_addr, IRQ3, (uint8_t)CLEAR_ALL_IRQ8 );\r
+ break;\r
+ \r
+ default:\r
+ HAL_ASSERT(0);\r
+ break;\r
+ }\r
+}\r
+\r
+/*-------------------------------------------------------------------------*//**\r
+ * GPIO_config\r
+ * See "core_gpio.h" for details of how to use this function.\r
+ */\r
+void GPIO_config\r
+(\r
+ gpio_instance_t * this_gpio,\r
+ gpio_id_t port_id,\r
+ uint32_t config\r
+)\r
+{\r
+ HAL_ASSERT( port_id < NB_OF_GPIO );\r
+ \r
+ if ( port_id < NB_OF_GPIO )\r
+ {\r
+ uint32_t cfg_reg_addr = this_gpio->base_addr;\r
+ cfg_reg_addr += (port_id * 4);\r
+ HW_set_32bit_reg( cfg_reg_addr, config );\r
+ \r
+ /*\r
+ * Verify that the configuration was correctly written. Failure to read\r
+ * back the expected value may indicate that the GPIO port was configured\r
+ * as part of the hardware flow and cannot be modified through software.\r
+ * It may also indicate that the base address passed as parameter to\r
+ * GPIO_init() was incorrect.\r
+ */\r
+ HAL_ASSERT( HW_get_32bit_reg( cfg_reg_addr ) == config );\r
+ }\r
+}\r
+\r
+/*-------------------------------------------------------------------------*//**\r
+ * GPIO_set_outputs\r
+ * See "core_gpio.h" for details of how to use this function.\r
+ */\r
+void GPIO_set_outputs\r
+(\r
+ gpio_instance_t * this_gpio,\r
+ uint32_t value\r
+)\r
+{\r
+ switch( this_gpio->apb_bus_width )\r
+ {\r
+ case GPIO_APB_32_BITS_BUS:\r
+ HAL_set_32bit_reg( this_gpio->base_addr, GPIO_OUT, value );\r
+ break;\r
+ \r
+ case GPIO_APB_16_BITS_BUS:\r
+ HAL_set_16bit_reg( this_gpio->base_addr, GPIO_OUT0, (uint16_t)value );\r
+ HAL_set_16bit_reg( this_gpio->base_addr, GPIO_OUT1, (uint16_t)(value >> 16) );\r
+ break;\r
+ \r
+ case GPIO_APB_8_BITS_BUS:\r
+ HAL_set_8bit_reg( this_gpio->base_addr, GPIO_OUT0, (uint8_t)value );\r
+ HAL_set_8bit_reg( this_gpio->base_addr, GPIO_OUT1, (uint8_t)(value >> 8) );\r
+ HAL_set_8bit_reg( this_gpio->base_addr, GPIO_OUT2, (uint8_t)(value >> 16) );\r
+ HAL_set_8bit_reg( this_gpio->base_addr, GPIO_OUT3, (uint8_t)(value >> 24) );\r
+ break;\r
+ \r
+ default:\r
+ HAL_ASSERT(0);\r
+ break;\r
+ }\r
+ \r
+ /*\r
+ * Verify that the output register was correctly written. Failure to read back\r
+ * the expected value may indicate that some of the GPIOs may not exist due to\r
+ * the number of GPIOs selected in the CoreGPIO hardware flow configuration.\r
+ * It may also indicate that the base address or APB bus width passed as\r
+ * parameter to the GPIO_init() function do not match the hardware design.\r
+ */\r
+ HAL_ASSERT( GPIO_get_outputs( this_gpio ) == value );\r
+}\r
+\r
+/*-------------------------------------------------------------------------*//**\r
+ * GPIO_get_inputs\r
+ * See "core_gpio.h" for details of how to use this function.\r
+ */\r
+uint32_t GPIO_get_inputs\r
+(\r
+ gpio_instance_t * this_gpio\r
+)\r
+{\r
+ uint32_t gpio_in = 0;\r
+ \r
+ switch( this_gpio->apb_bus_width )\r
+ {\r
+ case GPIO_APB_32_BITS_BUS:\r
+ gpio_in = HAL_get_32bit_reg( this_gpio->base_addr, GPIO_IN );\r
+ break;\r
+ \r
+ case GPIO_APB_16_BITS_BUS:\r
+ gpio_in |= HAL_get_16bit_reg( this_gpio->base_addr, GPIO_IN0 );\r
+ gpio_in |= (HAL_get_16bit_reg( this_gpio->base_addr, GPIO_IN1 ) << 16);\r
+ break;\r
+ \r
+ case GPIO_APB_8_BITS_BUS:\r
+ gpio_in |= HAL_get_8bit_reg( this_gpio->base_addr, GPIO_IN0 );\r
+ gpio_in |= (HAL_get_8bit_reg( this_gpio->base_addr, GPIO_IN1 ) << 8);\r
+ gpio_in |= (HAL_get_8bit_reg( this_gpio->base_addr, GPIO_IN2 ) << 16);\r
+ gpio_in |= (HAL_get_8bit_reg( this_gpio->base_addr, GPIO_IN3 ) << 24);\r
+ break;\r
+ \r
+ default:\r
+ HAL_ASSERT(0);\r
+ break;\r
+ }\r
+ \r
+ return gpio_in;\r
+}\r
+\r
+/*-------------------------------------------------------------------------*//**\r
+ * GPIO_get_outputs\r
+ * See "core_gpio.h" for details of how to use this function.\r
+ */\r
+uint32_t GPIO_get_outputs\r
+(\r
+ gpio_instance_t * this_gpio\r
+)\r
+{\r
+ uint32_t gpio_out = 0;\r
+ \r
+ switch( this_gpio->apb_bus_width )\r
+ {\r
+ case GPIO_APB_32_BITS_BUS:\r
+ gpio_out = HAL_get_32bit_reg( this_gpio->base_addr, GPIO_OUT );\r
+ break;\r
+ \r
+ case GPIO_APB_16_BITS_BUS:\r
+ gpio_out |= HAL_get_16bit_reg( this_gpio->base_addr, GPIO_OUT0 );\r
+ gpio_out |= (HAL_get_16bit_reg( this_gpio->base_addr, GPIO_OUT1 ) << 16);\r
+ break;\r
+ \r
+ case GPIO_APB_8_BITS_BUS:\r
+ gpio_out |= HAL_get_16bit_reg( this_gpio->base_addr, GPIO_OUT0 );\r
+ gpio_out |= (HAL_get_16bit_reg( this_gpio->base_addr, GPIO_OUT1 ) << 8);\r
+ gpio_out |= (HAL_get_16bit_reg( this_gpio->base_addr, GPIO_OUT2 ) << 16);\r
+ gpio_out |= (HAL_get_16bit_reg( this_gpio->base_addr, GPIO_OUT3 ) << 24);\r
+ break;\r
+ \r
+ default:\r
+ HAL_ASSERT(0);\r
+ break;\r
+ }\r
+ \r
+ return gpio_out;\r
+}\r
+\r
+/*-------------------------------------------------------------------------*//**\r
+ * GPIO_set_output\r
+ * See "core_gpio.h" for details of how to use this function.\r
+ */\r
+void GPIO_set_output\r
+(\r
+ gpio_instance_t * this_gpio,\r
+ gpio_id_t port_id,\r
+ uint8_t value\r
+)\r
+{\r
+ HAL_ASSERT( port_id < NB_OF_GPIO );\r
+ \r
+ \r
+ switch( this_gpio->apb_bus_width )\r
+ {\r
+ case GPIO_APB_32_BITS_BUS:\r
+ {\r
+ uint32_t outputs_state;\r
+ \r
+ outputs_state = HAL_get_32bit_reg( this_gpio->base_addr, GPIO_OUT );\r
+ if ( 0 == value )\r
+ {\r
+ outputs_state &= ~(1 << port_id);\r
+ }\r
+ else\r
+ {\r
+ outputs_state |= 1 << port_id;\r
+ }\r
+ HAL_set_32bit_reg( this_gpio->base_addr, GPIO_OUT, outputs_state );\r
+ \r
+ /*\r
+ * Verify that the output register was correctly written. Failure to read back\r
+ * the expected value may indicate that some of the GPIOs may not exist due to\r
+ * the number of GPIOs selected in the CoreGPIO hardware flow configuration.\r
+ * It may also indicate that the base address or APB bus width passed as\r
+ * parameter to the GPIO_init() function do not match the hardware design.\r
+ */\r
+ HAL_ASSERT( HAL_get_32bit_reg( this_gpio->base_addr, GPIO_OUT ) == outputs_state );\r
+ }\r
+ break;\r
+ \r
+ case GPIO_APB_16_BITS_BUS:\r
+ {\r
+ uint16_t outputs_state;\r
+ uint32_t gpio_out_reg_addr = this_gpio->base_addr + GPIO_OUT_REG_OFFSET + ((port_id >> 4) * 4);\r
+ \r
+ outputs_state = HW_get_16bit_reg( gpio_out_reg_addr );\r
+ if ( 0 == value )\r
+ {\r
+ outputs_state &= ~(1 << (port_id & 0x0F));\r
+ }\r
+ else\r
+ {\r
+ outputs_state |= 1 << (port_id & 0x0F);\r
+ }\r
+ HW_set_16bit_reg( gpio_out_reg_addr, outputs_state );\r
+ \r
+ /*\r
+ * Verify that the output register was correctly written. Failure to read back\r
+ * the expected value may indicate that some of the GPIOs may not exist due to\r
+ * the number of GPIOs selected in the CoreGPIO hardware flow configuration.\r
+ * It may also indicate that the base address or APB bus width passed as\r
+ * parameter to the GPIO_init() function do not match the hardware design.\r
+ */\r
+ HAL_ASSERT( HW_get_16bit_reg( gpio_out_reg_addr ) == outputs_state );\r
+ }\r
+ break;\r
+ \r
+ case GPIO_APB_8_BITS_BUS:\r
+ {\r
+ uint8_t outputs_state;\r
+ uint32_t gpio_out_reg_addr = this_gpio->base_addr + GPIO_OUT_REG_OFFSET + ((port_id >> 3) * 4);\r
+ \r
+ outputs_state = HW_get_8bit_reg( gpio_out_reg_addr );\r
+ if ( 0 == value )\r
+ {\r
+ outputs_state &= ~(1 << (port_id & 0x07));\r
+ }\r
+ else\r
+ {\r
+ outputs_state |= 1 << (port_id & 0x07);\r
+ }\r
+ HW_set_8bit_reg( gpio_out_reg_addr, outputs_state );\r
+ \r
+ /*\r
+ * Verify that the output register was correctly written. Failure to read back\r
+ * the expected value may indicate that some of the GPIOs may not exist due to\r
+ * the number of GPIOs selected in the CoreGPIO hardware flow configuration.\r
+ * It may also indicate that the base address or APB bus width passed as\r
+ * parameter to the GPIO_init() function do not match the hardware design.\r
+ */\r
+ HAL_ASSERT( HW_get_8bit_reg( gpio_out_reg_addr ) == outputs_state );\r
+ }\r
+ break;\r
+ \r
+ default:\r
+ HAL_ASSERT(0);\r
+ break;\r
+ }\r
+}\r
+\r
+/*-------------------------------------------------------------------------*//**\r
+ * GPIO_drive_inout\r
+ * See "core_gpio.h" for details of how to use this function.\r
+ */\r
+void GPIO_drive_inout\r
+(\r
+ gpio_instance_t * this_gpio,\r
+ gpio_id_t port_id,\r
+ gpio_inout_state_t inout_state\r
+)\r
+{\r
+ uint32_t config;\r
+ uint32_t cfg_reg_addr = this_gpio->base_addr;\r
+ \r
+ HAL_ASSERT( port_id < NB_OF_GPIO );\r
+\r
+ switch( inout_state )\r
+ {\r
+ case GPIO_DRIVE_HIGH:\r
+ /* Set output high */\r
+ GPIO_set_output( this_gpio, port_id, 1 );\r
+ \r
+ /* Enable output buffer */\r
+ cfg_reg_addr = this_gpio->base_addr + (port_id * 4);\r
+ config = HW_get_8bit_reg( cfg_reg_addr );\r
+ config |= OUTPUT_BUFFER_ENABLE_MASK;\r
+ HW_set_8bit_reg( cfg_reg_addr, config );\r
+ break;\r
+ \r
+ case GPIO_DRIVE_LOW:\r
+ /* Set output low */\r
+ GPIO_set_output( this_gpio, port_id, 0 );\r
+ \r
+ /* Enable output buffer */\r
+ cfg_reg_addr = this_gpio->base_addr + (port_id * 4);\r
+ config = HW_get_8bit_reg( cfg_reg_addr );\r
+ config |= OUTPUT_BUFFER_ENABLE_MASK;\r
+ HW_set_8bit_reg( cfg_reg_addr, config );\r
+ break;\r
+ \r
+ case GPIO_HIGH_Z:\r
+ /* Disable output buffer */\r
+ cfg_reg_addr = this_gpio->base_addr + (port_id * 4);\r
+ config = HW_get_8bit_reg( cfg_reg_addr );\r
+ config &= ~OUTPUT_BUFFER_ENABLE_MASK;\r
+ HW_set_8bit_reg( cfg_reg_addr, config );\r
+ break;\r
+ \r
+ default:\r
+ HAL_ASSERT(0);\r
+ break;\r
+ }\r
+}\r
+\r
+/*-------------------------------------------------------------------------*//**\r
+ * GPIO_enable_irq\r
+ * See "core_gpio.h" for details of how to use this function.\r
+ */\r
+void GPIO_enable_irq\r
+(\r
+ gpio_instance_t * this_gpio,\r
+ gpio_id_t port_id\r
+)\r
+{\r
+ uint32_t cfg_value;\r
+ uint32_t cfg_reg_addr = this_gpio->base_addr;\r
+ \r
+ HAL_ASSERT( port_id < NB_OF_GPIO );\r
+ \r
+ if ( port_id < NB_OF_GPIO )\r
+ {\r
+ cfg_reg_addr += (port_id * 4);\r
+ cfg_value = HW_get_8bit_reg( cfg_reg_addr );\r
+ cfg_value |= GPIO_INT_ENABLE_MASK;\r
+ HW_set_8bit_reg( cfg_reg_addr, cfg_value );\r
+ }\r
+}\r
+\r
+/*-------------------------------------------------------------------------*//**\r
+ * GPIO_disable_irq\r
+ * See "core_gpio.h" for details of how to use this function.\r
+ */\r
+void GPIO_disable_irq\r
+(\r
+ gpio_instance_t * this_gpio,\r
+ gpio_id_t port_id\r
+)\r
+{\r
+ uint32_t cfg_value;\r
+ uint32_t cfg_reg_addr = this_gpio->base_addr;\r
+ \r
+ HAL_ASSERT( port_id < NB_OF_GPIO );\r
+ \r
+ if ( port_id < NB_OF_GPIO )\r
+ {\r
+ cfg_reg_addr += (port_id * 4);\r
+ cfg_value = HW_get_8bit_reg( cfg_reg_addr );\r
+ cfg_value &= ~GPIO_INT_ENABLE_MASK;\r
+ HW_set_8bit_reg( cfg_reg_addr, cfg_value );\r
+ }\r
+}\r
+\r
+/*-------------------------------------------------------------------------*//**\r
+ * GPIO_clear_irq\r
+ * See "core_gpio.h" for details of how to use this function.\r
+ */\r
+void GPIO_clear_irq\r
+(\r
+ gpio_instance_t * this_gpio,\r
+ gpio_id_t port_id\r
+)\r
+{\r
+ uint32_t irq_clr_value = ((uint32_t)1) << ((uint32_t)port_id);\r
+ \r
+ switch( this_gpio->apb_bus_width )\r
+ {\r
+ case GPIO_APB_32_BITS_BUS:\r
+ HAL_set_32bit_reg( this_gpio->base_addr, IRQ, irq_clr_value );\r
+ break;\r
+ \r
+ case GPIO_APB_16_BITS_BUS:\r
+ HAL_set_16bit_reg( this_gpio->base_addr, IRQ0, irq_clr_value );\r
+ HAL_set_16bit_reg( this_gpio->base_addr, IRQ1, irq_clr_value >> 16 );\r
+ break;\r
+ \r
+ case GPIO_APB_8_BITS_BUS:\r
+ HAL_set_8bit_reg( this_gpio->base_addr, IRQ0, irq_clr_value );\r
+ HAL_set_8bit_reg( this_gpio->base_addr, IRQ1, irq_clr_value >> 8 );\r
+ HAL_set_8bit_reg( this_gpio->base_addr, IRQ2, irq_clr_value >> 16 );\r
+ HAL_set_8bit_reg( this_gpio->base_addr, IRQ3, irq_clr_value >> 24 );\r
+ break;\r
+ \r
+ default:\r
+ HAL_ASSERT(0);\r
+ break;\r
+ }\r
+}\r
+\r
--- /dev/null
+/*******************************************************************************\r
+ * (c) Copyright 2008-2015 Microsemi SoC Products Group. All rights reserved.\r
+ * \r
+ * CoreGPIO bare metal driver public API.\r
+ *\r
+ * SVN $Revision: 7964 $\r
+ * SVN $Date: 2015-10-09 18:26:53 +0530 (Fri, 09 Oct 2015) $\r
+ */\r
+\r
+/*=========================================================================*//**\r
+ @mainpage CoreGPIO Bare Metal Driver.\r
+\r
+ @section intro_sec Introduction\r
+ The CoreGPIO hardware IP includes up to 32 general purpose input output GPIOs.\r
+ This driver provides a set of functions for controlling the GPIOs as part of a\r
+ bare metal system where no operating system is available. These drivers\r
+ can be adapted for use as part of an operating system but the implementation\r
+ of the adaptation layer between this driver and the operating system's driver\r
+ model is outside the scope of this driver.\r
+ \r
+ @section driver_configuration Driver Configuration\r
+ The CoreGPIO individual IOs can be configured either in the hardware flow or\r
+ as part of the software application through calls to the GPIO_config() function.\r
+ GPIOs configured as as part of the hardware is fixed and cannot be modified\r
+ using a call to the GPI_config() function.\r
+ \r
+ @section theory_op Theory of Operation\r
+ The CoreGPIO driver uses the Actel Hardware Abstraction Layer (HAL) to access\r
+ hardware registers. You must ensure that the Actel HAL is included as part of\r
+ your software project. The Actel HAL is available through the Actel Firmware\r
+ Catalog.\r
+ \r
+ The CoreGPIO driver functions are logically grouped into the following groups:\r
+ - Initiliazation\r
+ - Configuration\r
+ - Reading and writing GPIO state\r
+ - Interrupt control\r
+ \r
+ The CoreGPIO driver is initialized through a call to the GPIO_init() function.\r
+ The GPIO_init() function must be called before any other GPIO driver functions\r
+ can be called.\r
+ \r
+ Each GPIO port is individually configured through a call to the\r
+ GPIO_config() function. Configuration includes deciding if a GPIO port\r
+ will be used as input, output or both. GPIO ports configured as inputs can be\r
+ further configured to generate interrupts based on the input's state.\r
+ Interrupts can be level or edge sensitive.\r
+ Please note that a CoreGPIO hardware instance can be generated, as part of the\r
+ hardware flow, with a fixed configuration for some or all of its IOs. Attempting\r
+ to modify the configuration of such a hardware configured IO using the\r
+ GPIO_config() function has no effect.\r
+ \r
+ The state of the GPIO ports can be read and written using the following\r
+ functions:\r
+ - GPIO_get_inputs()\r
+ - GPIO_get_outputs()\r
+ - GPIO_set_outputs()\r
+ - GPIO_drive_inout()\r
+ \r
+ Interrupts generated by GPIO ports configured as inputs are controlled using\r
+ the following functions:\r
+ - GPIO_enable_irq()\r
+ - GPIO_disable_irq()\r
+ - GPIO_clear_irq()\r
+ \r
+ *//*=========================================================================*/\r
+#ifndef CORE_GPIO_H_\r
+#define CORE_GPIO_H_\r
+\r
+#include <stdint.h>\r
+#include "cpu_types.h"\r
+\r
+/*-------------------------------------------------------------------------*//**\r
+ The gpio_id_t enumeration is used to identify GPIOs as part of the\r
+ parameter to functions:\r
+ - GPIO_config(),\r
+ - GPIO_drive_inout(),\r
+ - GPIO_enable_int(),\r
+ - GPIO_disable_int(),\r
+ - GPIO_clear_int()\r
+ */\r
+typedef enum __gpio_id_t\r
+{\r
+ GPIO_0 = 0,\r
+ GPIO_1 = 1,\r
+ GPIO_2 = 2,\r
+ GPIO_3 = 3,\r
+ GPIO_4 = 4,\r
+ GPIO_5 = 5,\r
+ GPIO_6 = 6,\r
+ GPIO_7 = 7,\r
+ GPIO_8 = 8,\r
+ GPIO_9 = 9,\r
+ GPIO_10 = 10,\r
+ GPIO_11 = 11,\r
+ GPIO_12 = 12,\r
+ GPIO_13 = 13,\r
+ GPIO_14 = 14,\r
+ GPIO_15 = 15,\r
+ GPIO_16 = 16,\r
+ GPIO_17 = 17,\r
+ GPIO_18 = 18,\r
+ GPIO_19 = 19,\r
+ GPIO_20 = 20,\r
+ GPIO_21 = 21,\r
+ GPIO_22 = 22,\r
+ GPIO_23 = 23,\r
+ GPIO_24 = 24,\r
+ GPIO_25 = 25,\r
+ GPIO_26 = 26,\r
+ GPIO_27 = 27,\r
+ GPIO_28 = 28,\r
+ GPIO_29 = 29,\r
+ GPIO_30 = 30,\r
+ GPIO_31 = 31\r
+} gpio_id_t;\r
+\r
+typedef enum __gpio_apb_width_t\r
+{\r
+ GPIO_APB_8_BITS_BUS = 0,\r
+ GPIO_APB_16_BITS_BUS = 1,\r
+ GPIO_APB_32_BITS_BUS = 2,\r
+ GPIO_APB_UNKNOWN_BUS_WIDTH = 3\r
+} gpio_apb_width_t;\r
+\r
+/*-------------------------------------------------------------------------*//**\r
+ */\r
+typedef struct __gpio_instance_t\r
+{\r
+ addr_t base_addr;\r
+ gpio_apb_width_t apb_bus_width;\r
+} gpio_instance_t;\r
+\r
+/*-------------------------------------------------------------------------*//**\r
+ GPIO ports definitions used to identify GPIOs as part of the parameter to\r
+ function GPIO_set_outputs().\r
+ These definitions can also be used to identity GPIO through logical\r
+ operations on the return value of function GPIO_get_inputs().\r
+ */\r
+#define GPIO_0_MASK 0x00000001UL\r
+#define GPIO_1_MASK 0x00000002UL\r
+#define GPIO_2_MASK 0x00000004UL\r
+#define GPIO_3_MASK 0x00000008UL\r
+#define GPIO_4_MASK 0x00000010UL\r
+#define GPIO_5_MASK 0x00000020UL\r
+#define GPIO_6_MASK 0x00000040UL\r
+#define GPIO_7_MASK 0x00000080UL\r
+#define GPIO_8_MASK 0x00000100UL\r
+#define GPIO_9_MASK 0x00000200UL\r
+#define GPIO_10_MASK 0x00000400UL\r
+#define GPIO_11_MASK 0x00000800UL\r
+#define GPIO_12_MASK 0x00001000UL\r
+#define GPIO_13_MASK 0x00002000UL\r
+#define GPIO_14_MASK 0x00004000UL\r
+#define GPIO_15_MASK 0x00008000UL\r
+#define GPIO_16_MASK 0x00010000UL\r
+#define GPIO_17_MASK 0x00020000UL\r
+#define GPIO_18_MASK 0x00040000UL\r
+#define GPIO_19_MASK 0x00080000UL\r
+#define GPIO_20_MASK 0x00100000UL\r
+#define GPIO_21_MASK 0x00200000UL\r
+#define GPIO_22_MASK 0x00400000UL\r
+#define GPIO_23_MASK 0x00800000UL\r
+#define GPIO_24_MASK 0x01000000UL\r
+#define GPIO_25_MASK 0x02000000UL\r
+#define GPIO_26_MASK 0x04000000UL\r
+#define GPIO_27_MASK 0x08000000UL\r
+#define GPIO_28_MASK 0x10000000UL\r
+#define GPIO_29_MASK 0x20000000UL\r
+#define GPIO_30_MASK 0x40000000UL\r
+#define GPIO_31_MASK 0x80000000UL\r
+\r
+/*-------------------------------------------------------------------------*//**\r
+ * GPIO modes\r
+ */\r
+#define GPIO_INPUT_MODE 0x0000000002UL\r
+#define GPIO_OUTPUT_MODE 0x0000000005UL\r
+#define GPIO_INOUT_MODE 0x0000000003UL\r
+\r
+/*-------------------------------------------------------------------------*//**\r
+ * Possible GPIO inputs interrupt configurations.\r
+ */\r
+#define GPIO_IRQ_LEVEL_HIGH 0x0000000000UL\r
+#define GPIO_IRQ_LEVEL_LOW 0x0000000020UL\r
+#define GPIO_IRQ_EDGE_POSITIVE 0x0000000040UL\r
+#define GPIO_IRQ_EDGE_NEGATIVE 0x0000000060UL\r
+#define GPIO_IRQ_EDGE_BOTH 0x0000000080UL\r
+\r
+/*-------------------------------------------------------------------------*//**\r
+ * Possible states for GPIO configured as INOUT.\r
+ */\r
+typedef enum gpio_inout_state\r
+{\r
+ GPIO_DRIVE_LOW = 0,\r
+ GPIO_DRIVE_HIGH,\r
+ GPIO_HIGH_Z\r
+} gpio_inout_state_t;\r
+\r
+/*-------------------------------------------------------------------------*//**\r
+ The GPIO_init() function initialises a CoreGPIO hardware instance and the data\r
+ structure associated with the CoreGPIO hardware instance.\r
+ Please note that a CoreGPIO hardware instance can be generated with a fixed\r
+ configuration for some or all of its IOs as part of the hardware flow. Attempting\r
+ to modify the configuration of such a hardware configured IO using the\r
+ GPIO_config() function has no effect.\r
+\r
+ @param this_gpio\r
+ Pointer to the gpio_instance_t data structure instance holding all data\r
+ regarding the CoreGPIO hardware instance being initialized. A pointer to the\r
+ same data structure will be used in subsequent calls to the CoreGPIO driver\r
+ functions in order to identify the CoreGPIO instance that should perform the\r
+ operation implemented by the called driver function.\r
+\r
+ @param base_addr\r
+ The base_addr parameter is the base address in the processor's memory map for\r
+ the registers of the GPIO instance being initialized.\r
+ \r
+ @param bus_width\r
+ The bus_width parameter informs the driver of the APB bus width selected during\r
+ the hardware flow configuration of the CoreGPIO hardware instance. It indicates\r
+ to the driver whether the CoreGPIO hardware registers will be visible as 8, 16\r
+ or 32 bits registers. Allowed value are:\r
+ - GPIO_APB_8_BITS_BUS\r
+ - GPIO_APB_16_BITS_BUS\r
+ - GPIO_APB_32_BITS_BUS\r
+ \r
+ @return\r
+ none.\r
+ \r
+ Example:\r
+ @code\r
+ #define COREGPIO_BASE_ADDR 0xC2000000\r
+ \r
+ gpio_instance_t g_gpio;\r
+ \r
+ void system_init( void )\r
+ {\r
+ GPIO_init( &g_gpio, COREGPIO_BASE_ADDR, GPIO_APB_32_BITS_BUS );\r
+ }\r
+ @endcode\r
+ */\r
+void GPIO_init\r
+(\r
+ gpio_instance_t * this_gpio,\r
+ addr_t base_addr,\r
+ gpio_apb_width_t bus_width\r
+);\r
+\r
+/*-------------------------------------------------------------------------*//**\r
+ The GPIO_config() function is used to configure an individual GPIO port.\r
+ \r
+ @param this_gpio\r
+ The this_gpio parameter is a pointer to the gpio_instance_t structure holding\r
+ all data regarding the CoreGPIO instance controlled through this function call.\r
+\r
+ @param port_id\r
+ The port_id parameter identifies the GPIO port to be configured.\r
+ An enumeration item of the form GPIO_n where n is the number of the GPIO\r
+ port is used to identify the GPIO port. For example GPIO_0 identifies the\r
+ first GPIO port and GPIO_31 the last one.\r
+ \r
+ @param config\r
+ The config parameter specifies the configuration to be applied to the GPIO\r
+ port identified by the first parameter. It is a logical OR of GPIO mode and\r
+ the interrupt mode. The interrupt mode is only relevant if the GPIO is\r
+ configured as input.\r
+ Possible modes are:\r
+ - GPIO_INPUT_MODE,\r
+ - GPIO_OUTPUT_MODE,\r
+ - GPIO_INOUT_MODE.\r
+ Possible interrupt modes are:\r
+ - GPIO_IRQ_LEVEL_HIGH,\r
+ - GPIO_IRQ_LEVEL_LOW,\r
+ - GPIO_IRQ_EDGE_POSITIVE,\r
+ - GPIO_IRQ_EDGE_NEGATIVE,\r
+ - GPIO_IRQ_EDGE_BOTH\r
+ \r
+ @return\r
+ none.\r
+ \r
+ For example the following call will configure GPIO 4 as an input generating\r
+ interrupts on a low to high transition of the input:\r
+ @code\r
+ GPIO_config( &g_gpio, GPIO_4, GPIO_INPUT_MODE | GPIO_IRQ_EDGE_POSITIVE );\r
+ @endcode\r
+ */\r
+void GPIO_config\r
+(\r
+ gpio_instance_t * this_gpio,\r
+ gpio_id_t port_id,\r
+ uint32_t config\r
+);\r
+\r
+/*-------------------------------------------------------------------------*//**\r
+ The GPIO_set_outputs() function is used to set the state of the GPIO ports\r
+ configured as outputs.\r
+ \r
+ @param this_gpio\r
+ The this_gpio parameter is a pointer to the gpio_instance_t structure holding\r
+ all data regarding the CoreGPIO instance controlled through this function call.\r
+\r
+ @param value\r
+ The value parameter specifies the state of the GPIO ports configured as\r
+ outputs. It is a bit mask of the form (GPIO_n_MASK | GPIO_m_MASK) where n\r
+ and m are numbers identifying GPIOs.\r
+ For example (GPIO_0_MASK | GPIO_1_MASK | GPIO_2_MASK ) specifies that the\r
+ first, second and third GPIOs' must be set high and all other outputs set\r
+ low.\r
+\r
+ @return\r
+ none.\r
+ \r
+ Example 1:\r
+ Set GPIOs outputs 0 and 8 high and all other GPIO outputs low.\r
+ @code\r
+ GPIO_set_outputs( &g_gpio, GPIO_0_MASK | GPIO_8_MASK );\r
+ @endcode\r
+\r
+ Example 2:\r
+ Set GPIOs outputs 2 and 4 low without affecting other GPIO outputs.\r
+ @code\r
+ uint32_t gpio_outputs;\r
+ gpio_outputs = GPIO_get_outputs( &g_gpio );\r
+ gpio_outputs &= ~( GPIO_2_MASK | GPIO_4_MASK );\r
+ GPIO_set_outputs( &g_gpio, gpio_outputs );\r
+ @endcode\r
+\r
+ @see GPIO_get_outputs()\r
+ */\r
+void GPIO_set_outputs\r
+(\r
+ gpio_instance_t * this_gpio,\r
+ uint32_t value\r
+);\r
+\r
+/*-------------------------------------------------------------------------*//**\r
+ The GPIO_set_output() function is used to set the state of a single GPIO\r
+ port configured as output.\r
+ \r
+ @param this_gpio\r
+ The this_gpio parameter is a pointer to the gpio_instance_t structure holding\r
+ all data regarding the CoreGPIO instance controlled through this function call.\r
+\r
+ @param port_id\r
+ The port_id parameter specifies the GPIO port that will have its output set\r
+ by a call to this function.\r
+ \r
+ @param value\r
+ The value parameter specifies the desired state for the GPIO output. A value\r
+ of 0 will set the output low and a value of 1 will set the port high.\r
+ \r
+ @return\r
+ none.\r
+ */\r
+void GPIO_set_output\r
+(\r
+ gpio_instance_t * this_gpio,\r
+ gpio_id_t port_id,\r
+ uint8_t value\r
+);\r
+\r
+/*-------------------------------------------------------------------------*//**\r
+ The GPIO_get_inputs() function is used to read the state of all GPIOs\r
+ confgured as inputs.\r
+ \r
+ @param this_gpio\r
+ The this_gpio parameter is a pointer to the gpio_instance_t structure holding\r
+ all data regarding the CoreGPIO instance controlled through this function call.\r
+\r
+ @return\r
+ This function returns a 32 bit unsigned integer where each bit represents\r
+ the state of an input. The least significant bit representing the state of\r
+ GPIO 0 and the most significant bit the state of GPIO 31.\r
+ */\r
+uint32_t GPIO_get_inputs\r
+(\r
+ gpio_instance_t * this_gpio\r
+);\r
+\r
+/*-------------------------------------------------------------------------*//**\r
+ The GPIO_get_outputs() function is used to read the current state of all\r
+ GPIO outputs.\r
+ \r
+ @param this_gpio\r
+ The this_gpio parameter is a pointer to the gpio_instance_t structure holding\r
+ all data regarding the CoreGPIO instance controlled through this function call.\r
+\r
+ @return\r
+ This function returns a 32 bit unsigned integer where each bit represents\r
+ the state of an output. The least significant bit representing the state\r
+ of GPIO 0 and the most significant bit the state of GPIO 31.\r
+ */\r
+uint32_t GPIO_get_outputs\r
+(\r
+ gpio_instance_t * this_gpio\r
+);\r
+\r
+/*-------------------------------------------------------------------------*//**\r
+ The GPIO_drive_inout() function is used to set the output state of a\r
+ GPIO configured as INOUT. An INOUT GPIO can be in one of three states:\r
+ - high\r
+ - low\r
+ - high impedance\r
+ An INOUT output would typically be used where several devices can drive the\r
+ state of a signal. The high and low states are equivalent to the high and low\r
+ states of a GPIO configured as output. The high impedance state is used to\r
+ prevent the GPIO from driving the state of the output and therefore allow\r
+ reading the state of the GPIO as an input.\r
+ Please note that the GPIO port you wish to use as INOUT through this function\r
+ must be configurable through software. Therefore the GPIO ports used as INOUT\r
+ must not have a fixed configuration selected as part of the hardware flow.\r
+ \r
+ @param this_gpio\r
+ The this_gpio parameter is a pointer to the gpio_instance_t structure holding\r
+ all data regarding the CoreGPIO instance controlled through this function call.\r
+\r
+ @param port_id\r
+ The port_id parameter identifies the GPIO for whcih this function will\r
+ change the output state.\r
+ An enumeration item of the form GPIO_n where n is the number of the GPIO\r
+ port is used to identify the GPIO port. For example GPIO_0 identifies the\r
+ first GPIO port and GPIO_31 the last one.\r
+ \r
+ @param inout_state\r
+ The inout_state parameter specifies the state of the I/O identified by the\r
+ first parameter. Possible states are:\r
+ - GPIO_DRIVE_HIGH,\r
+ - GPIO_DRIVE_LOW,\r
+ - GPIO_HIGH_Z (high impedance)\r
+\r
+ @return\r
+ none.\r
+ \r
+ Example:\r
+ The call to GPIO_drive_inout() below will set the GPIO 7 output to\r
+ high impedance state.\r
+ @code\r
+ GPIO_drive_inout( &g_gpio, GPIO_7, GPIO_HIGH_Z );\r
+ @endcode\r
+ */\r
+void GPIO_drive_inout\r
+(\r
+ gpio_instance_t * this_gpio,\r
+ gpio_id_t port_id,\r
+ gpio_inout_state_t inout_state\r
+);\r
+\r
+/*-------------------------------------------------------------------------*//**\r
+ The GPIO_enable_irq() function is used to enable an interrupt to be\r
+ generated based on the state of the input identified as parameter.\r
+ \r
+ @param this_gpio\r
+ The this_gpio parameter is a pointer to the gpio_instance_t structure holding\r
+ all data regarding the CoreGPIO instance controlled through this function call.\r
+\r
+ @param port_id\r
+ The port_id parameter identifies the GPIO input the call to\r
+ GPIO_enable_irq() will enable to generate interrupts.\r
+ An enumeration item of the form GPIO_n where n is the number of the GPIO\r
+ port is used to identify the GPIO port. For example GPIO_0 identifies the\r
+ first GPIO port and GPIO_31 the last one.\r
+ \r
+ @return\r
+ none.\r
+ \r
+ Example:\r
+ The call to GPIO_enable_irq() below will allow GPIO 8 to generate\r
+ interrupts.\r
+ @code\r
+ GPIO_enable_irq( &g_gpio, GPIO_8 );\r
+ @endcode\r
+ */\r
+void GPIO_enable_irq\r
+(\r
+ gpio_instance_t * this_gpio,\r
+ gpio_id_t port_id\r
+);\r
+\r
+/*-------------------------------------------------------------------------*//**\r
+ The GPIO_disable_irq() function is used to disable interrupt from being\r
+ generated based on the state of the input specified as parameter.\r
+ \r
+ @param this_gpio\r
+ The this_gpio parameter is a pointer to the gpio_instance_t structure holding\r
+ all data regarding the CoreGPIO instance controlled through this function call.\r
+\r
+ @param port_id\r
+ The port_id parameter identifies the GPIO input the call to\r
+ GPIO_disable_irq() will disable from generating interrupts.\r
+ An enumeration item of the form GPIO_n where n is the number of the GPIO\r
+ port is used to identify the GPIO port. For example GPIO_0 identifies the\r
+ first GPIO port and GPIO_31 the last one.\r
+ \r
+ @return\r
+ none.\r
+ \r
+ Example:\r
+ The call to GPIO_disable_irq() below will prevent GPIO 8 from generating\r
+ interrupts.\r
+ @code\r
+ GPIO_disable_irq( &g_gpio, GPIO_8 );\r
+ @endcode\r
+ */\r
+void GPIO_disable_irq\r
+(\r
+ gpio_instance_t * this_gpio,\r
+ gpio_id_t port_id\r
+);\r
+\r
+/*-------------------------------------------------------------------------*//**\r
+ The GPIO_clear_irq() function is used to clear the interrupt generated by\r
+ the GPIO specified as parameter. The GPIO_clear_irq() function must be\r
+ called as part of a GPIO interrupt service routine (ISR) in order to prevent\r
+ the same interrupt event retriggering a call to the GPIO ISR.\r
+ Please note that interrupts may also need to be cleared in the processor's\r
+ interrupt controller.\r
+ \r
+ @param this_gpio\r
+ The this_gpio parameter is a pointer to the gpio_instance_t structure holding\r
+ all data regarding the CoreGPIO instance controlled through this function call.\r
+\r
+ @param port_id\r
+ The port_id parameter identifies the GPIO input for which to clear the\r
+ interrupt.\r
+ An enumeration item of the form GPIO_n where n is the number of the GPIO\r
+ port is used to identify the GPIO port. For example GPIO_0 identifies the\r
+ first GPIO port and GPIO_31 the last one.\r
+ \r
+ @return\r
+ none.\r
+ \r
+ Example:\r
+ The example below demonstrates the use of the GPIO_clear_irq() function as\r
+ part of the GPIO 9 interrupt service routine on a Cortex-M processor. \r
+ @code\r
+ void GPIO9_IRQHandler( void )\r
+ {\r
+ do_interrupt_processing();\r
+ \r
+ GPIO_clear_irq( &g_gpio, GPIO_9 );\r
+ \r
+ NVIC_ClearPendingIRQ( GPIO9_IRQn );\r
+ }\r
+ @endcode\r
+ */\r
+void GPIO_clear_irq\r
+(\r
+ gpio_instance_t * this_gpio,\r
+ gpio_id_t port_id\r
+);\r
+\r
+#endif /* CORE_GPIO_H_ */\r
--- /dev/null
+/*******************************************************************************\r
+ * (c) Copyright 2009-2015 Microsemi SoC Products Group. All rights reserved.\r
+ * \r
+ * SVN $Revision: 7964 $\r
+ * SVN $Date: 2015-10-09 18:26:53 +0530 (Fri, 09 Oct 2015) $\r
+ */\r
+#ifndef __CORE_GPIO_REGISTERS_H\r
+#define __CORE_GPIO_REGISTERS_H 1\r
+\r
+/*------------------------------------------------------------------------------\r
+ * \r
+ */\r
+#define IRQ_REG_OFFSET 0x80\r
+\r
+#define IRQ0_REG_OFFSET 0x80\r
+#define IRQ1_REG_OFFSET 0x84\r
+#define IRQ2_REG_OFFSET 0x88\r
+#define IRQ3_REG_OFFSET 0x8C\r
+\r
+/*------------------------------------------------------------------------------\r
+ * \r
+ */\r
+#define GPIO_IN_REG_OFFSET 0x90\r
+\r
+#define GPIO_IN0_REG_OFFSET 0x90\r
+#define GPIO_IN1_REG_OFFSET 0x94\r
+#define GPIO_IN2_REG_OFFSET 0x98\r
+#define GPIO_IN3_REG_OFFSET 0x9C\r
+\r
+/*------------------------------------------------------------------------------\r
+ * \r
+ */\r
+#define GPIO_OUT_REG_OFFSET 0xA0\r
+\r
+#define GPIO_OUT0_REG_OFFSET 0xA0\r
+#define GPIO_OUT1_REG_OFFSET 0xA4\r
+#define GPIO_OUT2_REG_OFFSET 0xA8\r
+#define GPIO_OUT3_REG_OFFSET 0xAC\r
+\r
+#endif /* __CORE_GPIO_REGISTERS_H */\r
--- /dev/null
+/*******************************************************************************\r
+ * (c) Copyright 2009-2015 Microsemi SoC Products Group. All rights reserved.\r
+ * \r
+ * CoreI2C software driver implementation.\r
+ * \r
+ * SVN $Revision: 7984 $\r
+ * SVN $Date: 2015-10-12 12:07:40 +0530 (Mon, 12 Oct 2015) $\r
+ */\r
+#include <stdint.h>\r
+#include <stdlib.h>\r
+#include <stddef.h>\r
+#include <unistd.h>\r
+#include <errno.h>\r
+#include <sys/stat.h>\r
+#include <sys/times.h>\r
+#include <stdio.h>\r
+#include <string.h>\r
+#include "cpu_types.h"\r
+#include "core_smbus_regs.h"\r
+#include "core_i2c.h"\r
+#include "hal.h"\r
+#include "hal_assert.h"\r
+\r
+\r
+#include <string.h>\r
+\r
+#ifdef __cplusplus\r
+extern "C" {\r
+#endif\r
+\r
+/*------------------------------------------------------------------------------\r
+ * I2C transaction direction.\r
+ */\r
+#define WRITE_DIR 0u\r
+#define READ_DIR 1u\r
+\r
+/* -- TRANSACTIONS TYPES -- */\r
+#define NO_TRANSACTION 0u\r
+#define MASTER_WRITE_TRANSACTION 1u\r
+#define MASTER_READ_TRANSACTION 2u\r
+#define MASTER_RANDOM_READ_TRANSACTION 3u\r
+#define WRITE_SLAVE_TRANSACTION 4u\r
+#define READ_SLAVE_TRANSACTION 5u\r
+\r
+/* -- SMBUS H/W STATES -- */\r
+/* -- MASTER STATES -- */\r
+#define ST_BUS_ERROR 0x00u /* Bus error during MST or selected slave modes */\r
+#define ST_I2C_IDLE 0xF8u /* No activity and no interrupt either... */\r
+#define ST_START 0x08u /* start condition sent */\r
+#define ST_RESTART 0x10u /* repeated start */\r
+#define ST_SLAW_ACK 0x18u /* SLA+W sent, ack received */\r
+#define ST_SLAW_NACK 0x20u /* SLA+W sent, nack received */\r
+#define ST_TX_DATA_ACK 0x28u /* Data sent, ACK'ed */\r
+#define ST_TX_DATA_NACK 0x30u /* Data sent, NACK'ed */\r
+#define ST_LOST_ARB 0x38u /* Master lost arbitration */\r
+#define ST_SLAR_ACK 0x40u /* SLA+R sent, ACK'ed */\r
+#define ST_SLAR_NACK 0x48u /* SLA+R sent, NACK'ed */\r
+#define ST_RX_DATA_ACK 0x50u /* Data received, ACK sent */\r
+#define ST_RX_DATA_NACK 0x58u /* Data received, NACK sent */\r
+#define ST_RESET_ACTIVATED 0xD0u /* Master reset is activated */\r
+#define ST_STOP_TRANSMIT 0xE0u /* Stop has been transmitted */\r
+\r
+/* -- SLAVE STATES -- */\r
+#define ST_SLAVE_SLAW 0x60u /* SLA+W received */\r
+#define ST_SLAVE_SLAR_ACK 0xA8u /* SLA+R received, ACK returned */\r
+#define ST_SLV_LA 0x68u /* Slave lost arbitration */\r
+#define ST_GCA 0x70u /* GCA received */\r
+#define ST_GCA_LA 0x78u /* GCA lost arbitration */\r
+#define ST_RDATA 0x80u /* Data received */\r
+#define ST_SLA_NACK 0x88u /* Slave addressed, NACK returned */\r
+#define ST_GCA_ACK 0x90u /* Previously addresses with GCA, data ACKed */\r
+#define ST_GCA_NACK 0x98u /* GCA addressed, NACK returned */\r
+#define ST_RSTOP 0xA0u /* Stop received */\r
+#define ST_SLARW_LA 0xB0u /* Arbitration lost */\r
+#define ST_RACK 0xB8u /* Byte sent, ACK received */\r
+#define ST_SLAVE_RNACK 0xC0u /* Byte sent, NACK received */\r
+#define ST_FINAL 0xC8u /* Final byte sent, ACK received */\r
+#define ST_SLV_RST 0xD8u /* Slave reset state */\r
+\r
+\r
+/* I2C Channel base offset */\r
+#define CHANNEL_BASE_SHIFT 5u\r
+#define CHANNEL_MASK 0x1E0u\r
+\r
+/*\r
+ * Maximum address offset length in slave write-read transactions.\r
+ * A maximum of two bytes will be interpreted as address offset within the slave\r
+ * tx buffer.\r
+ */\r
+#define MAX_OFFSET_LENGTH 2u\r
+\r
+/*------------------------------------------------------------------------------\r
+ * I2C interrupts control functions implemented "i2c_interrupt.c".\r
+ * the implementation of these functions depend on the underlying hardware\r
+ * design and how the CoreI2C interrupt line is connected to the system's\r
+ * interrupt controller.\r
+ */\r
+void I2C_enable_irq( i2c_instance_t * this_i2c );\r
+void I2C_disable_irq( i2c_instance_t * this_i2c );\r
+static void enable_slave_if_required(i2c_instance_t * this_i2c);\r
+\r
+/*------------------------------------------------------------------------------\r
+ * I2C_init()\r
+ * See "core_i2c.h" for details of how to use this function.\r
+ */\r
+void I2C_init\r
+(\r
+ i2c_instance_t * this_i2c,\r
+ addr_t base_address,\r
+ uint8_t ser_address,\r
+ i2c_clock_divider_t ser_clock_speed\r
+)\r
+{\r
+ psr_t saved_psr;\r
+ uint_fast16_t clock_speed = (uint_fast16_t)ser_clock_speed;\r
+ \r
+ /*\r
+ * We need to disable ints while doing this as there is no guarantee we\r
+ * have not been called already and the ISR is active.\r
+ */\r
+\r
+ saved_psr=HAL_disable_interrupts();\r
+ \r
+ /*\r
+ * Initialize all items of the this_i2c data structure to zero. This\r
+ * initializes all state variables to their init value. It relies on\r
+ * the fact that NO_TRANSACTION, I2C_SUCCESS and I2C_RELEASE_BUS all\r
+ * have an actual value of zero.\r
+ */\r
+ memset(this_i2c, 0, sizeof(i2c_instance_t));\r
+ \r
+ /*\r
+ * Set base address of I2C hardware used by this instance.\r
+ */\r
+ this_i2c->base_address = base_address;\r
+\r
+ /*\r
+ * Update Serial address of the device\r
+ */\r
+ this_i2c->ser_address = ((uint_fast8_t)ser_address << 1u);\r
+ \r
+ /*\r
+ * Configure hardware.\r
+ */\r
+ HAL_set_8bit_reg_field(this_i2c->base_address, ENS1, 0x00); /* Reset I2C hardware. */\r
+ HAL_set_8bit_reg_field(this_i2c->base_address, ENS1, 0x01); /* set enable bit */\r
+ HAL_set_8bit_reg_field(this_i2c->base_address, CR2, ( (clock_speed >> 2) & 0x01) );\r
+ HAL_set_8bit_reg_field(this_i2c->base_address, CR1, ( (clock_speed >> 1) & 0x01) );\r
+ HAL_set_8bit_reg_field(this_i2c->base_address, CR0, ( clock_speed & 0x01) );\r
+\r
+ HAL_set_8bit_reg(this_i2c->base_address, ADDRESS, this_i2c->ser_address);\r
+ HAL_set_8bit_reg(this_i2c->base_address, ADDRESS1, this_i2c->ser_address);\r
+ \r
+ /*\r
+ * Finally safe to enable interrupts.\r
+ */\r
+\r
+ HAL_restore_interrupts( saved_psr );\r
+}\r
+/*------------------------------------------------------------------------------\r
+ * I2C_channel_init()\r
+ * See "core_i2c.h" for details of how to use this function.\r
+ */\r
+void I2C_channel_init\r
+(\r
+ i2c_instance_t * this_i2c_channel,\r
+ i2c_instance_t * this_i2c,\r
+ i2c_channel_number_t channel_number,\r
+ i2c_clock_divider_t ser_clock_speed\r
+)\r
+{\r
+ psr_t saved_psr;\r
+ uint_fast16_t clock_speed = (uint_fast16_t)ser_clock_speed;\r
+ \r
+ HAL_ASSERT(channel_number < I2C_MAX_CHANNELS);\r
+ HAL_ASSERT(I2C_CHANNEL_0 != channel_number);\r
+\r
+ /* \r
+ * Cannot allow channel 0 in this function as we will trash the hardware\r
+ * base address and slave address.\r
+ */\r
+ if ((channel_number < I2C_MAX_CHANNELS) &&\r
+ (I2C_CHANNEL_0 != channel_number))\r
+ {\r
+ /*\r
+ * We need to disable ints while doing this as the hardware should already\r
+ * be active at this stage.\r
+ */\r
+\r
+ saved_psr=HAL_disable_interrupts();\r
+ /*\r
+ * Initialize channel data.\r
+ */\r
+ memset(this_i2c_channel, 0, sizeof(i2c_instance_t));\r
+ \r
+ this_i2c_channel->base_address =\r
+ ((this_i2c->base_address) & ~((addr_t)CHANNEL_MASK)) \r
+ | (((addr_t)channel_number) << CHANNEL_BASE_SHIFT);\r
+\r
+ this_i2c_channel->ser_address = this_i2c->ser_address;\r
+\r
+ HAL_set_8bit_reg_field(this_i2c_channel->base_address, ENS1, 0x00); /* Reset I2C channel hardware. */\r
+ HAL_set_8bit_reg_field(this_i2c_channel->base_address, ENS1, 0x01); /* set enable bit */\r
+ HAL_set_8bit_reg_field(this_i2c_channel->base_address, CR2, ( (clock_speed >> 2) & 0x01) );\r
+ HAL_set_8bit_reg_field(this_i2c_channel->base_address, CR1, ( (clock_speed >> 1) & 0x01) );\r
+ HAL_set_8bit_reg_field(this_i2c_channel->base_address, CR0, ( clock_speed & 0x01) );\r
+ /*\r
+ * Finally safe to enable interrupts.\r
+ */\r
+\r
+ HAL_restore_interrupts( saved_psr );\r
+ }\r
+}\r
+\r
+/*------------------------------------------------------------------------------\r
+ * I2C_write()\r
+ * See "core_i2c.h" for details of how to use this function.\r
+ */\r
+void I2C_write\r
+(\r
+ i2c_instance_t * this_i2c,\r
+ uint8_t serial_addr,\r
+ const uint8_t * write_buffer,\r
+ uint16_t write_size,\r
+ uint8_t options\r
+)\r
+{\r
+ psr_t saved_psr;\r
+ volatile uint8_t stat_ctrl;\r
+\r
+\r
+ saved_psr=HAL_disable_interrupts();\r
+\r
+ /* Update the transaction only when there is no transaction going on I2C */\r
+ if( this_i2c->transaction == NO_TRANSACTION)\r
+ {\r
+ this_i2c->transaction = MASTER_WRITE_TRANSACTION;\r
+ }\r
+\r
+ /* Update the Pending transaction information so that transaction can restarted */\r
+ this_i2c->pending_transaction = MASTER_WRITE_TRANSACTION ;\r
+\r
+ /* Update target address */\r
+ this_i2c->target_addr = (uint_fast8_t)serial_addr << 1u;\r
+ this_i2c->dir = WRITE_DIR;\r
+ this_i2c->master_tx_buffer = write_buffer;\r
+ this_i2c->master_tx_size = write_size;\r
+ this_i2c->master_tx_idx = 0u;\r
+\r
+ /* Set I2C status in progress */\r
+ this_i2c->master_status = I2C_IN_PROGRESS;\r
+ this_i2c->options = options;\r
+\r
+ if(I2C_IN_PROGRESS == this_i2c->slave_status)\r
+ {\r
+ this_i2c->is_transaction_pending = 1u;\r
+ }\r
+ else\r
+ {\r
+ HAL_set_8bit_reg_field(this_i2c->base_address, STA, 0x01u);\r
+ }\r
+\r
+ /*\r
+ * Clear interrupts if required (depends on repeated starts).\r
+ * Since the Bus is on hold, only then prior status needs to\r
+ * be cleared.\r
+ */\r
+ if ( I2C_HOLD_BUS == this_i2c->bus_status )\r
+ {\r
+ HAL_set_8bit_reg_field(this_i2c->base_address, SI, 0x00u);\r
+ }\r
+\r
+ stat_ctrl = HAL_get_8bit_reg( this_i2c->base_address, STATUS);\r
+ stat_ctrl = stat_ctrl; /* Avoids lint warning. */\r
+\r
+ /* Enable the interrupt. ( Re-enable) */\r
+ I2C_enable_irq( this_i2c );\r
+\r
+\r
+ HAL_restore_interrupts(saved_psr);\r
+}\r
+\r
+/*------------------------------------------------------------------------------\r
+ * I2C_read()\r
+ * See "core_i2c.h" for details of how to use this function.\r
+ */\r
+void I2C_read\r
+(\r
+ i2c_instance_t * this_i2c,\r
+ uint8_t serial_addr,\r
+ uint8_t * read_buffer,\r
+ uint16_t read_size,\r
+ uint8_t options\r
+)\r
+{\r
+ psr_t saved_psr;\r
+ volatile uint8_t stat_ctrl;\r
+\r
+\r
+ saved_psr=HAL_disable_interrupts();\r
+ \r
+ /* Update the transaction only when there is no transaction going on I2C */\r
+ if( this_i2c->transaction == NO_TRANSACTION)\r
+ {\r
+ this_i2c->transaction = MASTER_READ_TRANSACTION;\r
+ }\r
+\r
+ /* Update the Pending transaction information so that transaction can restarted */\r
+ this_i2c->pending_transaction = MASTER_READ_TRANSACTION ;\r
+\r
+ /* Update target address */\r
+ this_i2c->target_addr = (uint_fast8_t)serial_addr << 1u;\r
+\r
+ this_i2c->dir = READ_DIR;\r
+\r
+ this_i2c->master_rx_buffer = read_buffer;\r
+ this_i2c->master_rx_size = read_size;\r
+ this_i2c->master_rx_idx = 0u;\r
+\r
+ /* Set I2C status in progress */\r
+ this_i2c->master_status = I2C_IN_PROGRESS;\r
+\r
+ this_i2c->options = options;\r
+ \r
+ if(I2C_IN_PROGRESS == this_i2c->slave_status)\r
+ {\r
+ this_i2c->is_transaction_pending = 1u;\r
+ }\r
+ else\r
+ {\r
+ HAL_set_8bit_reg_field(this_i2c->base_address, STA, 0x01u);\r
+ }\r
+\r
+ /*\r
+ * Clear interrupts if required (depends on repeated starts).\r
+ * Since the Bus is on hold, only then prior status needs to\r
+ * be cleared.\r
+ */\r
+ if ( I2C_HOLD_BUS == this_i2c->bus_status )\r
+ {\r
+ HAL_set_8bit_reg_field(this_i2c->base_address, SI, 0x00u);\r
+ }\r
+\r
+ stat_ctrl = HAL_get_8bit_reg( this_i2c->base_address, STATUS);\r
+ stat_ctrl = stat_ctrl; /* Avoids lint warning. */\r
+\r
+ /* Enable the interrupt. ( Re-enable) */\r
+ I2C_enable_irq( this_i2c );\r
+\r
+ HAL_restore_interrupts( saved_psr );\r
+\r
+}\r
+\r
+/*------------------------------------------------------------------------------\r
+ * I2C_write_read()\r
+ * See "core_i2c.h" for details of how to use this function.\r
+ */\r
+void I2C_write_read\r
+(\r
+ i2c_instance_t * this_i2c,\r
+ uint8_t serial_addr,\r
+ const uint8_t * addr_offset,\r
+ uint16_t offset_size,\r
+ uint8_t * read_buffer,\r
+ uint16_t read_size,\r
+ uint8_t options\r
+)\r
+{\r
+ HAL_ASSERT(offset_size > 0u);\r
+ HAL_ASSERT(addr_offset != (uint8_t *)0);\r
+ HAL_ASSERT(read_size > 0u);\r
+ HAL_ASSERT(read_buffer != (uint8_t *)0);\r
+ \r
+ this_i2c->master_status = I2C_FAILED;\r
+ \r
+ if((read_size > 0u) && (offset_size > 0u))\r
+ {\r
+ psr_t saved_psr;\r
+ volatile uint8_t stat_ctrl;\r
+\r
+\r
+ saved_psr=HAL_disable_interrupts();\r
+\r
+ /* Update the transaction only when there is no transaction going on I2C */\r
+ if( this_i2c->transaction == NO_TRANSACTION)\r
+ {\r
+ this_i2c->transaction = MASTER_RANDOM_READ_TRANSACTION;\r
+ }\r
+\r
+ /* Update the Pending transaction information so that transaction can restarted */\r
+ this_i2c->pending_transaction = MASTER_RANDOM_READ_TRANSACTION ;\r
+\r
+ /* Update target address */\r
+ this_i2c->target_addr = (uint_fast8_t)serial_addr << 1u;\r
+\r
+ this_i2c->dir = WRITE_DIR;\r
+\r
+ this_i2c->master_tx_buffer = addr_offset;\r
+ this_i2c->master_tx_size = offset_size;\r
+ this_i2c->master_tx_idx = 0u;\r
+\r
+ this_i2c->master_rx_buffer = read_buffer;\r
+ this_i2c->master_rx_size = read_size;\r
+ this_i2c->master_rx_idx = 0u;\r
+ \r
+ /* Set I2C status in progress */\r
+ this_i2c->master_status = I2C_IN_PROGRESS;\r
+ this_i2c->options = options;\r
+ \r
+ if(I2C_IN_PROGRESS == this_i2c->slave_status)\r
+ {\r
+ this_i2c->is_transaction_pending = 1u;\r
+ }\r
+ else\r
+ {\r
+ HAL_set_8bit_reg_field(this_i2c->base_address, STA, 0x01u);\r
+ }\r
+\r
+ /*\r
+ * Clear interrupts if required (depends on repeated starts).\r
+ * Since the Bus is on hold, only then prior status needs to\r
+ * be cleared.\r
+ */\r
+ if ( I2C_HOLD_BUS == this_i2c->bus_status )\r
+ {\r
+ HAL_set_8bit_reg_field(this_i2c->base_address, SI, 0x00u);\r
+ }\r
+\r
+ stat_ctrl = HAL_get_8bit_reg( this_i2c->base_address, STATUS);\r
+ stat_ctrl = stat_ctrl; /* Avoids lint warning. */\r
+ \r
+ /* Enable the interrupt. ( Re-enable) */\r
+ I2C_enable_irq( this_i2c );\r
+\r
+\r
+ HAL_restore_interrupts( saved_psr );\r
+ }\r
+}\r
+\r
+/*------------------------------------------------------------------------------\r
+ * I2C_get_status()\r
+ * See "core_i2c.h" for details of how to use this function.\r
+ */\r
+i2c_status_t I2C_get_status\r
+(\r
+ i2c_instance_t * this_i2c\r
+)\r
+{\r
+ i2c_status_t i2c_status ;\r
+\r
+ i2c_status = this_i2c->master_status ;\r
+\r
+ return i2c_status;\r
+}\r
+\r
+/*------------------------------------------------------------------------------\r
+ * I2C_wait_complete()\r
+ * See "core_i2c.h" for details of how to use this function.\r
+ */\r
+i2c_status_t I2C_wait_complete\r
+(\r
+ i2c_instance_t * this_i2c,\r
+ uint32_t timeout_ms\r
+)\r
+{\r
+ i2c_status_t i2c_status;\r
+ psr_t saved_psr;\r
+ /*\r
+ * Because we have no idea of what CPU we are supposed to be running on\r
+ * we need to guard this write to the timeout value to avoid ISR/user code\r
+ * interaction issues. Checking the status below should be fine as only a\r
+ * single byte should change in that.\r
+ */\r
+\r
+ saved_psr=HAL_disable_interrupts();\r
+ this_i2c->master_timeout_ms = timeout_ms;\r
+\r
+ HAL_restore_interrupts( saved_psr );\r
+\r
+ /* Run the loop until state returns I2C_FAILED or I2C_SUCESS*/\r
+ do {\r
+ i2c_status = this_i2c->master_status;\r
+ } while(I2C_IN_PROGRESS == i2c_status);\r
+ return i2c_status;\r
+}\r
+\r
+/*------------------------------------------------------------------------------\r
+ * I2C_system_tick()\r
+ * See "core_i2c.h" for details of how to use this function.\r
+ */\r
+void I2C_system_tick\r
+(\r
+ i2c_instance_t * this_i2c,\r
+ uint32_t ms_since_last_tick\r
+)\r
+{\r
+ if(this_i2c->master_timeout_ms != I2C_NO_TIMEOUT)\r
+ {\r
+ if(this_i2c->master_timeout_ms > ms_since_last_tick)\r
+ {\r
+ this_i2c->master_timeout_ms -= ms_since_last_tick;\r
+ }\r
+ else\r
+ {\r
+ psr_t saved_psr;\r
+ /*\r
+ * We need to disable interrupts here to ensure we can update the\r
+ * shared data without the I2C ISR interrupting us.\r
+ */\r
+\r
+ saved_psr=HAL_disable_interrupts();\r
+\r
+ /*\r
+ * Mark current transaction as having timed out.\r
+ */\r
+ this_i2c->master_status = I2C_TIMED_OUT;\r
+ this_i2c->transaction = NO_TRANSACTION;\r
+ this_i2c->is_transaction_pending = 0;\r
+\r
+\r
+ HAL_restore_interrupts( saved_psr );\r
+ \r
+ /*\r
+ * Make sure we do not incorrectly signal a timeout for subsequent\r
+ * transactions.\r
+ */\r
+ this_i2c->master_timeout_ms = I2C_NO_TIMEOUT;\r
+ }\r
+ }\r
+}\r
+\r
+/*------------------------------------------------------------------------------\r
+ * I2C_set_slave_tx_buffer()\r
+ * See "core_i2c.h" for details of how to use this function.\r
+ */\r
+void I2C_set_slave_tx_buffer\r
+(\r
+ i2c_instance_t * this_i2c,\r
+ const uint8_t * tx_buffer,\r
+ uint16_t tx_size\r
+)\r
+{\r
+ psr_t saved_psr;\r
+\r
+ /*\r
+ * We need to disable interrupts here to ensure we can update the\r
+ * shared data without the I2C ISR interrupting us.\r
+ */\r
+\r
+ saved_psr=HAL_disable_interrupts();\r
+ \r
+ this_i2c->slave_tx_buffer = tx_buffer;\r
+ this_i2c->slave_tx_size = tx_size;\r
+ this_i2c->slave_tx_idx = 0u;\r
+ \r
+\r
+ HAL_restore_interrupts( saved_psr );\r
+}\r
+\r
+/*------------------------------------------------------------------------------\r
+ * I2C_set_slave_rx_buffer()\r
+ * See "core_i2c.h" for details of how to use this function.\r
+ */\r
+void I2C_set_slave_rx_buffer\r
+(\r
+ i2c_instance_t * this_i2c,\r
+ uint8_t * rx_buffer,\r
+ uint16_t rx_size\r
+)\r
+{\r
+ psr_t saved_psr;\r
+\r
+ /*\r
+ * We need to disable interrupts here to ensure we can update the\r
+ * shared data without the I2C ISR interrupting us.\r
+ */\r
+\r
+ saved_psr=HAL_disable_interrupts();\r
+\r
+ this_i2c->slave_rx_buffer = rx_buffer;\r
+ this_i2c->slave_rx_size = rx_size;\r
+ this_i2c->slave_rx_idx = 0u;\r
+\r
+\r
+ HAL_restore_interrupts( saved_psr );\r
+}\r
+\r
+/*------------------------------------------------------------------------------\r
+ * I2C_set_slave_mem_offset_length()\r
+ * See "core_i2c.h" for details of how to use this function.\r
+ */\r
+void I2C_set_slave_mem_offset_length\r
+(\r
+ i2c_instance_t * this_i2c,\r
+ uint8_t offset_length\r
+)\r
+{\r
+ HAL_ASSERT(offset_length <= MAX_OFFSET_LENGTH);\r
+ \r
+ /*\r
+ * Single byte update, should be interrupt safe\r
+ */\r
+ if(offset_length > MAX_OFFSET_LENGTH)\r
+ {\r
+ this_i2c->slave_mem_offset_length = MAX_OFFSET_LENGTH;\r
+ }\r
+ else\r
+ {\r
+ this_i2c->slave_mem_offset_length = offset_length;\r
+ }\r
+}\r
+\r
+/*------------------------------------------------------------------------------\r
+ * I2C_register_write_handler()\r
+ * See "core_i2c.h" for details of how to use this function.\r
+ */\r
+void I2C_register_write_handler\r
+(\r
+ i2c_instance_t * this_i2c,\r
+ i2c_slave_wr_handler_t handler\r
+)\r
+{\r
+ psr_t saved_psr;\r
+\r
+ /*\r
+ * We need to disable interrupts here to ensure we can update the\r
+ * shared data without the I2C ISR interrupting us.\r
+ */\r
+\r
+ saved_psr=HAL_disable_interrupts();\r
+\r
+ this_i2c->slave_write_handler = handler;\r
+\r
+\r
+ HAL_restore_interrupts( saved_psr );\r
+}\r
+\r
+/*------------------------------------------------------------------------------\r
+ * I2C_enable_slave()\r
+ * See "core_i2c.h" for details of how to use this function.\r
+ */\r
+void I2C_enable_slave\r
+(\r
+ i2c_instance_t * this_i2c\r
+)\r
+{\r
+ psr_t saved_psr;\r
+\r
+ /*\r
+ * We need to disable interrupts here to ensure we can update the\r
+ * hardware register and slave mode flag without the I2C ISR interrupting\r
+ * us.\r
+ */\r
+\r
+ saved_psr=HAL_disable_interrupts();\r
+\r
+ /* Set the Assert Acknowledge bit. */\r
+ HAL_set_8bit_reg_field(this_i2c->base_address, AA, 0x01u);\r
+\r
+ /* Enable slave mode */\r
+ this_i2c->is_slave_enabled = 1u;\r
+\r
+\r
+ HAL_restore_interrupts( saved_psr );\r
+\r
+ /* Enable I2C IRQ*/\r
+ I2C_enable_irq( this_i2c );\r
+}\r
+\r
+/*------------------------------------------------------------------------------\r
+ * I2C_disable_slave()\r
+ * See "core_i2c.h" for details of how to use this function.\r
+ */\r
+void I2C_disable_slave\r
+(\r
+ i2c_instance_t * this_i2c\r
+)\r
+{\r
+ psr_t saved_psr;\r
+\r
+ /*\r
+ * We need to disable interrupts here to ensure we can update the\r
+ * hardware register without the I2C ISR interrupting us.\r
+ */\r
+\r
+ saved_psr=HAL_disable_interrupts();\r
+ \r
+ /* Reset the assert acknowledge bit. */\r
+ HAL_set_8bit_reg_field(this_i2c->base_address, AA, 0x00u);\r
+\r
+ /* Disable slave mode with IRQ blocked to make whole change atomic */\r
+ this_i2c->is_slave_enabled = 0u;\r
+\r
+\r
+ HAL_restore_interrupts( saved_psr );\r
+}\r
+\r
+/*------------------------------------------------------------------------------\r
+ * \r
+ */\r
+static void enable_slave_if_required\r
+(\r
+ i2c_instance_t * this_i2c\r
+)\r
+{\r
+ /*\r
+ * This function is only called from within the ISR and so does not need\r
+ * guarding on the register access.\r
+ */\r
+ if( 0 != this_i2c->is_slave_enabled )\r
+ {\r
+ HAL_set_8bit_reg_field( this_i2c->base_address, AA, 0x01u );\r
+ }\r
+}\r
+/*------------------------------------------------------------------------------\r
+ * I2C_set_slave_second_addr()\r
+ * See "i2c.h" for details of how to use this function.\r
+ */\r
+void I2C_set_slave_second_addr\r
+(\r
+ i2c_instance_t * this_i2c,\r
+ uint8_t second_slave_addr\r
+)\r
+{\r
+ uint8_t second_slave_address;\r
+ \r
+ /*\r
+ This function does not support CoreI2C hardware configured with a fixed \r
+ second slave address. The current implementation of the ADDR1[0] register\r
+ bit makes it difficult for the driver to support both programmable and\r
+ fixed second slave address, so we choose to support programmable only.\r
+ With the programmable configuration, ADDR1[0] and ADDR0[0] both control\r
+ enable/disable of GCA recognition, as an effective OR of the 2 bit fields.\r
+ Therefore we set ADDR1[0] to 0 here, so that only ADDR0[0] controls GCA.\r
+ */\r
+ second_slave_address = (uint8_t)((second_slave_addr << 1u) & (~SLAVE1_EN_MASK));\r
+\r
+ /*\r
+ * Single byte register write, should be interrupt safe\r
+ */\r
+ HAL_set_8bit_reg(this_i2c->base_address, ADDRESS1, second_slave_address);\r
+}\r
+\r
+/*------------------------------------------------------------------------------\r
+ * I2C_disable_slave_second_addr()\r
+ * See "i2c.h" for details of how to use this function.\r
+ */\r
+void I2C_disable_slave_second_addr\r
+(\r
+ i2c_instance_t * this_i2c\r
+)\r
+{\r
+ /*\r
+ We are disabling the second slave address by setting the value of the 2nd\r
+ slave address to the primary slave address. The reason for using this method\r
+ of disabling 2nd slave address is that ADDRESS1[0] has different meaning \r
+ depending on hardware configuration. Its use would likely interfere with\r
+ the intended GCA setting.\r
+ */\r
+ /*\r
+ * Single byte register write, should be interrupt safe\r
+ */\r
+ HAL_set_8bit_reg(this_i2c->base_address, ADDRESS1, this_i2c->ser_address);\r
+}\r
+\r
+/*------------------------------------------------------------------------------\r
+ * i2C_set_gca()\r
+ * See "i2c.h" for details of how to use this function.\r
+ */\r
+\r
+void I2C_set_gca\r
+(\r
+ i2c_instance_t * this_i2c\r
+)\r
+{\r
+ /* \r
+ * This read modify write access should be interrupt safe as the address\r
+ * register is not written to in the ISR.\r
+ */\r
+ /* accept GC addressing. */\r
+ HAL_set_8bit_reg_field(this_i2c->base_address, GC, 0x01u);\r
+}\r
+\r
+/*------------------------------------------------------------------------------\r
+ * I2C_clear_gca()\r
+ * See "i2c.h" for details of how to use this function.\r
+ */\r
+void I2C_clear_gca\r
+(\r
+ i2c_instance_t * this_i2c\r
+)\r
+{\r
+ /* \r
+ * This read modify write access should be interrupt safe as the address\r
+ * register is not written to in the ISR.\r
+ */\r
+ /* Clear GC addressing. */\r
+ HAL_set_8bit_reg_field(this_i2c->base_address, GC, 0x00u);\r
+}\r
+\r
+/*------------------------------------------------------------------------------\r
+ * I2C_isr()\r
+ * See "core_i2c.h" for details of how to use this function.\r
+ */\r
+void I2C_isr\r
+(\r
+ i2c_instance_t * this_i2c\r
+)\r
+{\r
+ volatile uint8_t status;\r
+ uint8_t data;\r
+ uint8_t hold_bus;\r
+ uint8_t clear_irq = 1u;\r
+\r
+ status = HAL_get_8bit_reg( this_i2c->base_address, STATUS);\r
+ \r
+ switch( status )\r
+ {\r
+ /************** MASTER TRANSMITTER / RECEIVER *******************/\r
+ \r
+ case ST_START: /* start has been xmt'd */\r
+ case ST_RESTART: /* repeated start has been xmt'd */\r
+ //write_hex(STDOUT_FILENO, status);\r
+ HAL_set_8bit_reg_field( this_i2c->base_address, STA, 0x00u);\r
+ HAL_set_8bit_reg( this_i2c->base_address, DATA, this_i2c->target_addr); /* write call address */\r
+ HAL_set_8bit_reg_field( this_i2c->base_address, DIR, this_i2c->dir); /* set direction bit */\r
+ if(this_i2c->dir == WRITE_DIR)\r
+ {\r
+ this_i2c->master_tx_idx = 0u;\r
+ }\r
+ else\r
+ {\r
+ this_i2c->master_rx_idx = 0u;\r
+ }\r
+\r
+ /*\r
+ * Clear the pending transaction. This condition will be true if the slave \r
+ * has acquired the bus to carry out pending master transaction which \r
+ * it had received during its slave transmission or reception mode. \r
+ */\r
+ if(this_i2c->is_transaction_pending)\r
+ {\r
+ this_i2c->is_transaction_pending = 0u;\r
+ }\r
+\r
+ /*\r
+ * Make sure to update proper transaction after master START\r
+ * or RESTART\r
+ */\r
+ if(this_i2c->transaction != this_i2c->pending_transaction)\r
+ {\r
+ this_i2c->transaction = this_i2c->pending_transaction;\r
+ }\r
+ break;\r
+ \r
+ case ST_LOST_ARB:\r
+ /* Set start bit. Let's keep trying! Don't give up! */\r
+ HAL_set_8bit_reg_field(this_i2c->base_address, STA, 0x01u);\r
+ break;\r
+\r
+ case ST_STOP_TRANSMIT:\r
+ /* Stop has been transmitted. Do nothing */\r
+ break;\r
+\r
+ /******************* MASTER TRANSMITTER *************************/\r
+ case ST_SLAW_NACK:\r
+ //write_hex(STDOUT_FILENO, status);\r
+ /* SLA+W has been transmitted; not ACK has been received - let's stop. */\r
+ HAL_set_8bit_reg_field(this_i2c->base_address, STO, 0x01u);\r
+ this_i2c->master_status = I2C_FAILED;\r
+ this_i2c->transaction = NO_TRANSACTION;\r
+ enable_slave_if_required(this_i2c);\r
+ break;\r
+ \r
+ case ST_SLAW_ACK:\r
+ case ST_TX_DATA_ACK:\r
+ //write_hex(STDOUT_FILENO, status);\r
+ /* data byte has been xmt'd with ACK, time to send stop bit or repeated start. */\r
+ if (this_i2c->master_tx_idx < this_i2c->master_tx_size)\r
+ { \r
+ HAL_set_8bit_reg(this_i2c->base_address, DATA, (uint_fast8_t)this_i2c->master_tx_buffer[this_i2c->master_tx_idx++]);\r
+ }\r
+ else if ( this_i2c->transaction == MASTER_RANDOM_READ_TRANSACTION )\r
+ {\r
+ /* We are finished sending the address offset part of a random read transaction.\r
+ * It is is time to send a restart in order to change direction. */\r
+ this_i2c->dir = READ_DIR;\r
+ HAL_set_8bit_reg_field(this_i2c->base_address, STA, 0x01u);\r
+ }\r
+ else /* done sending. let's stop */\r
+ {\r
+ /*\r
+ * Set the transaction back to NO_TRANSACTION to allow user to do further\r
+ * transaction\r
+ */\r
+ this_i2c->transaction = NO_TRANSACTION;\r
+ hold_bus = this_i2c->options & I2C_HOLD_BUS;\r
+\r
+ /* Store the information of current I2C bus status in the bus_status*/\r
+ this_i2c->bus_status = hold_bus;\r
+ if ( hold_bus == 0u )\r
+ { \r
+ HAL_set_8bit_reg_field(this_i2c->base_address, STO, 0x01u); /*xmt stop condition */\r
+ enable_slave_if_required(this_i2c);\r
+ }\r
+ else\r
+ {\r
+ I2C_disable_irq( this_i2c );\r
+ clear_irq = 0u;\r
+ }\r
+ this_i2c->master_status = I2C_SUCCESS;\r
+ }\r
+ break;\r
+\r
+ case ST_TX_DATA_NACK:\r
+ //write_hex(STDOUT_FILENO, status);\r
+ /* data byte SENT, ACK to be received\r
+ * In fact, this means we've received a NACK (This may not be \r
+ * obvious, but if we've rec'd an ACK then we would be in state \r
+ * 0x28!) hence, let's send a stop bit\r
+ */\r
+ HAL_set_8bit_reg_field(this_i2c->base_address, STO, 0x01u);/* xmt stop condition */\r
+ this_i2c->master_status = I2C_FAILED;\r
+\r
+ /*\r
+ * Set the transaction back to NO_TRANSACTION to allow user to do further\r
+ * transaction\r
+ */\r
+ this_i2c->transaction = NO_TRANSACTION;\r
+ enable_slave_if_required(this_i2c);\r
+ break;\r
+ \r
+ /********************* MASTER (or slave?) RECEIVER *************************/\r
+ \r
+ /* STATUS codes 08H, 10H, 38H are all covered in MTX mode */\r
+ case ST_SLAR_ACK: /* SLA+R tx'ed. */\r
+// //write_hex(STDOUT_FILENO, status);\r
+ /* Let's make sure we ACK the first data byte received (set AA bit in CTRL) unless\r
+ * the next byte is the last byte of the read transaction.\r
+ */\r
+ if(this_i2c->master_rx_size > 1u)\r
+ {\r
+ HAL_set_8bit_reg_field(this_i2c->base_address, AA, 0x01u);\r
+ }\r
+ else if(1u == this_i2c->master_rx_size)\r
+ {\r
+ HAL_set_8bit_reg_field(this_i2c->base_address, AA, 0x00u);\r
+ }\r
+ else /* this_i2c->master_rx_size == 0u */\r
+ {\r
+ HAL_set_8bit_reg_field(this_i2c->base_address, AA, 0x01u);\r
+ HAL_set_8bit_reg_field(this_i2c->base_address, STO, 0x01u);\r
+ this_i2c->master_status = I2C_SUCCESS;\r
+ this_i2c->transaction = NO_TRANSACTION;\r
+ }\r
+ break;\r
+ \r
+ case ST_SLAR_NACK: /* SLA+R tx'ed; let's release the bus (send a stop condition) */\r
+// //write_hex(STDOUT_FILENO, status);\r
+ HAL_set_8bit_reg_field(this_i2c->base_address, STO, 0x01u);\r
+ this_i2c->master_status = I2C_FAILED;\r
+\r
+ /*\r
+ * Set the transaction back to NO_TRANSACTION to allow user to do further\r
+ * transaction\r
+ */\r
+ this_i2c->transaction = NO_TRANSACTION;\r
+ enable_slave_if_required(this_i2c);\r
+ break;\r
+ \r
+ case ST_RX_DATA_ACK: /* Data byte received, ACK returned */\r
+// //write_hex(STDOUT_FILENO, status);\r
+ /* First, get the data */\r
+ this_i2c->master_rx_buffer[this_i2c->master_rx_idx++] = HAL_get_8bit_reg(this_i2c->base_address, DATA);\r
+ if( this_i2c->master_rx_idx >= (this_i2c->master_rx_size - 1u))\r
+ {\r
+ /* If we're at the second last byte, let's set AA to 0 so\r
+ * we return a NACK at the last byte. */\r
+ HAL_set_8bit_reg_field(this_i2c->base_address, AA, 0x00u);\r
+ }\r
+ break;\r
+ \r
+ case ST_RX_DATA_NACK: /* Data byte received, NACK returned */\r
+// //write_hex(STDOUT_FILENO, status);\r
+ /* Get the data, then send a stop condition */\r
+ this_i2c->master_rx_buffer[this_i2c->master_rx_idx] = HAL_get_8bit_reg(this_i2c->base_address, DATA);\r
+ \r
+ hold_bus = this_i2c->options & I2C_HOLD_BUS; \r
+\r
+ /* Store the information of current I2C bus status in the bus_status*/\r
+ this_i2c->bus_status = hold_bus;\r
+ if ( hold_bus == 0u )\r
+ { \r
+ HAL_set_8bit_reg_field(this_i2c->base_address, STO, 0x01u); /*xmt stop condition */\r
+\r
+ /* Bus is released, now we can start listening to bus, if it is slave */\r
+ enable_slave_if_required(this_i2c);\r
+ }\r
+ else\r
+ {\r
+ I2C_disable_irq( this_i2c );\r
+ clear_irq = 0u;\r
+ }\r
+ /*\r
+ * Set the transaction back to NO_TRANSACTION to allow user to do further\r
+ * transaction\r
+ */\r
+ this_i2c->transaction = NO_TRANSACTION;\r
+ this_i2c->master_status = I2C_SUCCESS;\r
+ break;\r
+ \r
+ /******************** SLAVE RECEIVER **************************/\r
+ case ST_GCA_NACK: /* NACK after, GCA addressing */\r
+ case ST_SLA_NACK: /* Re-enable AA (assert ack) bit for future transmissions */\r
+ //write_hex(STDOUT_FILENO, status);\r
+ HAL_set_8bit_reg_field(this_i2c->base_address, AA, 0x01u);\r
+\r
+ this_i2c->transaction = NO_TRANSACTION;\r
+ this_i2c->slave_status = I2C_SUCCESS;\r
+ \r
+ /* Check if transaction was pending. If yes, set the START bit */\r
+ if(this_i2c->is_transaction_pending)\r
+ {\r
+ HAL_set_8bit_reg_field(this_i2c->base_address, STA, 0x01u);\r
+ }\r
+ break;\r
+ \r
+ case ST_GCA_LA: /* Arbitr. lost (GCA rec'd) */\r
+ case ST_SLV_LA: /* Arbitr. lost (SLA rec'd) */\r
+ //write_hex(STDOUT_FILENO, status);\r
+ /*\r
+ * We lost arbitration and either the GCE or our address was the\r
+ * one received so pend the master operation we were starting.\r
+ */\r
+ this_i2c->is_transaction_pending = 1u;\r
+ /* Fall through to normal ST processing as we are now in slave mode */\r
+\r
+ case ST_GCA: /* General call address received, ACK returned */\r
+ case ST_SLAVE_SLAW: /* SLA+W received, ACK returned */\r
+ //write_hex(STDOUT_FILENO, status);\r
+ this_i2c->transaction = WRITE_SLAVE_TRANSACTION;\r
+ this_i2c->slave_rx_idx = 0u;\r
+ this_i2c->random_read_addr = 0u;\r
+ /*\r
+ * If Start Bit is set clear it, but store that information since it is because of\r
+ * pending transaction\r
+ */\r
+ if(HAL_get_8bit_reg_field(this_i2c->base_address, STA))\r
+ {\r
+ HAL_set_8bit_reg_field(this_i2c->base_address, STA, 0x00u);\r
+ this_i2c->is_transaction_pending = 1u;\r
+ }\r
+ this_i2c->slave_status = I2C_IN_PROGRESS;\r
+#ifdef INCLUDE_SLA_IN_RX_PAYLOAD\r
+ /* Fall through to put address as first byte in payload buffer */\r
+#else\r
+ /* Only break from this case if the slave address must NOT be included at the\r
+ * beginning of the received write data. */\r
+ break;\r
+#endif \r
+ case ST_GCA_ACK: /* DATA received; ACK sent after GCA */\r
+ case ST_RDATA: /* DATA received; must clear DATA register */\r
+ //write_hex(STDOUT_FILENO, status);\r
+ if((this_i2c->slave_rx_buffer != (uint8_t *)0)\r
+ && (this_i2c->slave_rx_idx < this_i2c->slave_rx_size))\r
+ {\r
+ data = HAL_get_8bit_reg(this_i2c->base_address, DATA);\r
+ this_i2c->slave_rx_buffer[this_i2c->slave_rx_idx++] = data;\r
+ \r
+#ifdef INCLUDE_SLA_IN_RX_PAYLOAD\r
+ if((ST_RDATA == status) || (ST_GCA_ACK == status))\r
+ {\r
+ /* Ignore the slave address byte in the random read address\r
+ computation in the case where INCLUDE_SLA_IN_RX_PAYLOAD\r
+ is defined. */\r
+#endif\r
+ this_i2c->random_read_addr = (this_i2c->random_read_addr << 8) + data;\r
+#ifdef INCLUDE_SLA_IN_RX_PAYLOAD\r
+ }\r
+#endif\r
+ }\r
+ \r
+ if(this_i2c->slave_rx_idx >= this_i2c->slave_rx_size)\r
+ {\r
+ /* Rx buffer is full. NACK next received byte. */\r
+ HAL_set_8bit_reg_field(this_i2c->base_address, AA, 0x00u); \r
+ }\r
+ break;\r
+ \r
+ case ST_RSTOP:\r
+ //write_hex(STDOUT_FILENO, status);\r
+ /* STOP or repeated START occurred. */\r
+ /* We cannot be sure if the transaction has actually completed as\r
+ * this hardware state reports that either a STOP or repeated START\r
+ * condition has occurred. We assume that this is a repeated START\r
+ * if the transaction was a write from the master to this point.*/\r
+ if ( this_i2c->transaction == WRITE_SLAVE_TRANSACTION )\r
+ {\r
+ if ( this_i2c->slave_rx_idx == this_i2c->slave_mem_offset_length )\r
+ {\r
+ this_i2c->slave_tx_idx = this_i2c->random_read_addr;\r
+ }\r
+ /* Call the slave's write transaction handler if it exists. */\r
+ if ( this_i2c->slave_write_handler != 0u )\r
+ {\r
+ i2c_slave_handler_ret_t h_ret;\r
+ h_ret = this_i2c->slave_write_handler( this_i2c, this_i2c->slave_rx_buffer, (uint16_t)this_i2c->slave_rx_idx );\r
+ if ( I2C_REENABLE_SLAVE_RX == h_ret )\r
+ {\r
+ /* There is a small risk that the write handler could\r
+ * call I2C_disable_slave() but return\r
+ * I2C_REENABLE_SLAVE_RX in error so we only enable\r
+ * ACKs if still in slave mode. */\r
+ enable_slave_if_required(this_i2c);\r
+ }\r
+ else\r
+ {\r
+ HAL_set_8bit_reg_field( this_i2c->base_address, AA, 0x0u );\r
+ /* Clear slave mode flag as well otherwise in mixed\r
+ * master/slave applications, the AA bit will get set by\r
+ * subsequent master operations. */\r
+ this_i2c->is_slave_enabled = 0u;\r
+ }\r
+ }\r
+ else\r
+ {\r
+ /* Re-enable address acknowledge in case we were ready to nack the next received byte. */\r
+ HAL_set_8bit_reg_field( this_i2c->base_address, AA, 0x01u );\r
+ }\r
+ }\r
+ else /* A stop or repeated start outside a write/read operation */\r
+ {\r
+ /*\r
+ * Reset slave_tx_idx so that a subsequent read will result in the slave's\r
+ * transmit buffer being sent from the first byte.\r
+ */\r
+ this_i2c->slave_tx_idx = 0u;\r
+ /*\r
+ * See if we need to re-enable acknowledgement as some error conditions, such\r
+ * as a master prematurely ending a transfer, can see us get here with AA set\r
+ * to 0 which will disable slave operation if we are not careful.\r
+ */\r
+ enable_slave_if_required(this_i2c);\r
+ }\r
+\r
+ /* Mark any previous master write transaction as complete. */\r
+ this_i2c->slave_status = I2C_SUCCESS;\r
+ \r
+ /* Check if transaction was pending. If yes, set the START bit */\r
+ if(this_i2c->is_transaction_pending)\r
+ {\r
+ HAL_set_8bit_reg_field(this_i2c->base_address, STA, 0x01u);\r
+ }\r
+\r
+ /*\r
+ * Set the transaction back to NO_TRANSACTION to allow user to do further\r
+ * transaction\r
+ */\r
+ this_i2c->transaction = NO_TRANSACTION;\r
+\r
+ break;\r
+ \r
+ case ST_SLV_RST: /* SMBUS ONLY: timeout state. must clear interrupt */\r
+ //write_hex(STDOUT_FILENO, status);\r
+ /*\r
+ * Set the transaction back to NO_TRANSACTION to allow user to do further\r
+ * transaction.\r
+ */\r
+ this_i2c->transaction = NO_TRANSACTION;\r
+ /*\r
+ * Reset slave_tx_idx so that a subsequent read will result in the slave's\r
+ * transmit buffer being sent from the first byte.\r
+ */\r
+ this_i2c->slave_tx_idx = 0u;\r
+ /*\r
+ * Clear status to I2C_FAILED only if there was an operation in progress.\r
+ */\r
+ if(I2C_IN_PROGRESS == this_i2c->slave_status)\r
+ {\r
+ this_i2c->slave_status = I2C_FAILED;\r
+ }\r
+\r
+ enable_slave_if_required(this_i2c); /* Make sure AA is set correctly */\r
+\r
+ break;\r
+ \r
+ /****************** SLAVE TRANSMITTER **************************/\r
+ case ST_SLAVE_SLAR_ACK: /* SLA+R received, ACK returned */\r
+ case ST_SLARW_LA: /* Arbitration lost, and: */\r
+ case ST_RACK: /* Data tx'ed, ACK received */\r
+ //write_hex(STDOUT_FILENO, status);\r
+ if ( status == ST_SLAVE_SLAR_ACK )\r
+ {\r
+ this_i2c->transaction = READ_SLAVE_TRANSACTION;\r
+ this_i2c->random_read_addr = 0u;\r
+ this_i2c->slave_status = I2C_IN_PROGRESS;\r
+ /* If Start Bit is set clear it, but store that information since it is because of\r
+ * pending transaction\r
+ */\r
+ if(HAL_get_8bit_reg_field(this_i2c->base_address, STA))\r
+ {\r
+ HAL_set_8bit_reg_field(this_i2c->base_address, STA, 0x00u);\r
+ this_i2c->is_transaction_pending = 1u;\r
+ }\r
+ }\r
+ if (this_i2c->slave_tx_idx >= this_i2c->slave_tx_size)\r
+ {\r
+ /* Ensure 0xFF is returned to the master when the slave specifies\r
+ * an empty transmit buffer. */\r
+ HAL_set_8bit_reg(this_i2c->base_address, DATA, 0xFFu);\r
+ }\r
+ else\r
+ {\r
+ /* Load the data the data byte to be sent to the master. */\r
+ HAL_set_8bit_reg(this_i2c->base_address, DATA, (uint_fast8_t)this_i2c->slave_tx_buffer[this_i2c->slave_tx_idx++]);\r
+ }\r
+ /* Determine if this is the last data byte to send to the master. */\r
+ if (this_i2c->slave_tx_idx >= this_i2c->slave_tx_size) /* last byte? */\r
+ {\r
+ HAL_set_8bit_reg_field(this_i2c->base_address, AA, 0x00u); \r
+ /* Next read transaction will result in slave's transmit buffer\r
+ * being sent from the first byte. */\r
+ this_i2c->slave_tx_idx = 0u;\r
+ }\r
+ break;\r
+ \r
+ case ST_SLAVE_RNACK: /* Data byte has been transmitted; not-ACK has been received. */\r
+ case ST_FINAL: /* Last Data byte tx'ed, ACK received */\r
+ //write_hex(STDOUT_FILENO, status);\r
+ /* We assume that the transaction will be stopped by the master.\r
+ * Reset slave_tx_idx so that a subsequent read will result in the slave's\r
+ * transmit buffer being sent from the first byte. */\r
+ this_i2c->slave_tx_idx = 0u;\r
+ HAL_set_8bit_reg_field(this_i2c->base_address, AA, 0x01u); \r
+\r
+ /* Mark previous state as complete */\r
+ this_i2c->slave_status = I2C_SUCCESS;\r
+ /* Check if transaction was pending. If yes, set the START bit */\r
+ if(this_i2c->is_transaction_pending)\r
+ {\r
+ HAL_set_8bit_reg_field(this_i2c->base_address, STA, 0x01u);\r
+ }\r
+ /*\r
+ * Set the transaction back to NO_TRANSACTION to allow user to do further\r
+ * transaction\r
+ */\r
+ this_i2c->transaction = NO_TRANSACTION;\r
+\r
+ break;\r
+\r
+ /* Master Reset has been activated Wait 35 ms for interrupt to be set,\r
+ * clear interrupt and proceed to 0xF8 state. */\r
+ case ST_RESET_ACTIVATED:\r
+ case ST_BUS_ERROR: /* Bus error during MST or selected slave modes */\r
+ default:\r
+ //write_hex(STDOUT_FILENO, status);\r
+ /* Some undefined state has encountered. Clear Start bit to make\r
+ * sure, next good transaction happen */\r
+ HAL_set_8bit_reg_field(this_i2c->base_address, STA, 0x00u);\r
+ /*\r
+ * Set the transaction back to NO_TRANSACTION to allow user to do further\r
+ * transaction.\r
+ */\r
+ this_i2c->transaction = NO_TRANSACTION;\r
+ /*\r
+ * Reset slave_tx_idx so that a subsequent read will result in the slave's\r
+ * transmit buffer being sent from the first byte.\r
+ */\r
+ this_i2c->slave_tx_idx = 0u;\r
+ /*\r
+ * Clear statuses to I2C_FAILED only if there was an operation in progress.\r
+ */\r
+ if(I2C_IN_PROGRESS == this_i2c->master_status)\r
+ {\r
+ this_i2c->master_status = I2C_FAILED;\r
+ }\r
+\r
+ if(I2C_IN_PROGRESS == this_i2c->slave_status)\r
+ {\r
+ this_i2c->slave_status = I2C_FAILED;\r
+ }\r
+\r
+ break;\r
+ }\r
+ \r
+ if ( clear_irq )\r
+ {\r
+ /* clear interrupt. */\r
+ HAL_set_8bit_reg_field(this_i2c->base_address, SI, 0x00u);\r
+ }\r
+ \r
+ /* Read the status register to ensure the last I2C registers write took place\r
+ * in a system built around a bus making use of posted writes. */\r
+// status = HAL_get_8bit_reg( this_i2c->base_address, STATUS);\r
+}\r
+\r
+/*------------------------------------------------------------------------------\r
+ * I2C_smbus_init()\r
+ * See "i2c.h" for details of how to use this function.\r
+ */\r
+ \r
+/*\r
+ * SMBSUS_NO = 1\r
+ * SMBALERT_NO = 1\r
+ * SMBus enable = 1\r
+ */\r
+#define INIT_AND_ENABLE_SMBUS 0x54u\r
+void I2C_smbus_init\r
+(\r
+ i2c_instance_t * this_i2c\r
+)\r
+{\r
+ /*\r
+ * Single byte register write, should be interrupt safe\r
+ */\r
+ /* Enable SMBUS */\r
+ HAL_set_8bit_reg(this_i2c->base_address, SMBUS, INIT_AND_ENABLE_SMBUS);\r
+}\r
+\r
+/*------------------------------------------------------------------------------\r
+ * I2C_enable_smbus_irq()\r
+ * See "i2c.h" for details of how to use this function.\r
+ */\r
+void I2C_enable_smbus_irq\r
+(\r
+ i2c_instance_t * this_i2c,\r
+ uint8_t irq_type\r
+)\r
+{\r
+ psr_t saved_psr;\r
+\r
+ /*\r
+ * We need to disable interrupts here to ensure we can update the\r
+ * hardware register without the SMBUS IRQs interrupting us.\r
+ */\r
+\r
+ saved_psr=HAL_disable_interrupts();\r
+\r
+ if ( irq_type & I2C_SMBALERT_IRQ)\r
+ {\r
+ HAL_set_8bit_reg_field(this_i2c->base_address, SMBALERT_IE, 0x01u);\r
+ }\r
+ if ( irq_type & I2C_SMBSUS_IRQ)\r
+ {\r
+ HAL_set_8bit_reg_field(this_i2c->base_address, SMBSUS_IE, 0x01u);\r
+ }\r
+ \r
+\r
+ HAL_restore_interrupts( saved_psr );\r
+}\r
+\r
+/*------------------------------------------------------------------------------\r
+ * I2C_disable_smbus_irq()\r
+ * See "i2c.h" for details of how to use this function.\r
+ */\r
+void I2C_disable_smbus_irq\r
+(\r
+ i2c_instance_t * this_i2c,\r
+ uint8_t irq_type\r
+)\r
+{\r
+ psr_t saved_psr;\r
+\r
+ /*\r
+ * We need to disable interrupts here to ensure we can update the\r
+ * hardware register without the SMBUS IRQs interrupting us.\r
+ */\r
+\r
+ saved_psr=HAL_disable_interrupts();\r
+\r
+ if ( irq_type & I2C_SMBALERT_IRQ)\r
+ {\r
+ HAL_set_8bit_reg_field(this_i2c->base_address, SMBALERT_IE, 0x00u);\r
+ }\r
+ if (irq_type & I2C_SMBSUS_IRQ )\r
+ {\r
+ HAL_set_8bit_reg_field(this_i2c->base_address, SMBSUS_IE, 0x00u);\r
+ }\r
+ \r
+\r
+ HAL_restore_interrupts( saved_psr );\r
+}\r
+\r
+/*------------------------------------------------------------------------------\r
+ * I2C_suspend_smbus_slave()\r
+ * See "i2c.h" for details of how to use this function.\r
+ */\r
+void I2C_suspend_smbus_slave\r
+(\r
+ i2c_instance_t * this_i2c\r
+)\r
+{\r
+ psr_t saved_psr;\r
+\r
+ /*\r
+ * We need to disable interrupts here to ensure we can update the\r
+ * hardware register without the SMBUS IRQs interrupting us.\r
+ */\r
+\r
+ saved_psr=HAL_disable_interrupts();\r
+\r
+ HAL_set_8bit_reg_field(this_i2c->base_address, SMBSUS_NO_CONTROL, 0x00u);\r
+\r
+\r
+ HAL_restore_interrupts( saved_psr );\r
+}\r
+\r
+/*------------------------------------------------------------------------------\r
+ * I2C_resume_smbus_slave()\r
+ * See "i2c.h" for details of how to use this function.\r
+ */\r
+void I2C_resume_smbus_slave\r
+(\r
+ i2c_instance_t * this_i2c\r
+)\r
+{\r
+ psr_t saved_psr;\r
+\r
+ /*\r
+ * We need to disable interrupts here to ensure we can update the\r
+ * hardware register without the SMBUS IRQs interrupting us.\r
+ */\r
+\r
+ saved_psr=HAL_disable_interrupts();\r
+\r
+ HAL_set_8bit_reg_field(this_i2c->base_address, SMBSUS_NO_CONTROL, 0x01u);\r
+\r
+\r
+ HAL_restore_interrupts( saved_psr );\r
+}\r
+\r
+/*------------------------------------------------------------------------------\r
+ * I2C_reset_smbus()\r
+ * See "i2c.h" for details of how to use this function.\r
+ */\r
+void I2C_reset_smbus\r
+(\r
+ i2c_instance_t * this_i2c\r
+)\r
+{\r
+ psr_t saved_psr;\r
+\r
+ /*\r
+ * We need to disable interrupts here to ensure we can update the\r
+ * hardware register without the SMBUS IRQs interrupting us.\r
+ */\r
+\r
+ saved_psr=HAL_disable_interrupts();\r
+ HAL_set_8bit_reg_field(this_i2c->base_address, SMBUS_MST_RESET, 0x01u);\r
+ \r
+\r
+ HAL_restore_interrupts( saved_psr );\r
+}\r
+\r
+/*------------------------------------------------------------------------------\r
+ * I2C_set_smbus_alert()\r
+ * See "i2c.h" for details of how to use this function.\r
+ */\r
+void I2C_set_smbus_alert\r
+(\r
+ i2c_instance_t * this_i2c\r
+)\r
+{\r
+ psr_t saved_psr;\r
+\r
+ /*\r
+ * We need to disable interrupts here to ensure we can update the\r
+ * hardware register without the SMBUS IRQs interrupting us.\r
+ */\r
+\r
+ saved_psr=HAL_disable_interrupts();\r
+ HAL_set_8bit_reg_field(this_i2c->base_address, SMBALERT_NO_CONTROL, 0x00u);\r
+\r
+\r
+ HAL_restore_interrupts( saved_psr );\r
+}\r
+\r
+/*------------------------------------------------------------------------------\r
+ * I2C_clear_smbus_alert()\r
+ * See "i2c.h" for details of how to use this function.\r
+ */\r
+void I2C_clear_smbus_alert\r
+(\r
+ i2c_instance_t * this_i2c\r
+)\r
+{\r
+ psr_t saved_psr;\r
+\r
+ /*\r
+ * We need to disable interrupts here to ensure we can update the\r
+ * hardware register without the SMBUS IRQs interrupting us.\r
+ */\r
+\r
+ saved_psr=HAL_disable_interrupts();\r
+\r
+ HAL_set_8bit_reg_field(this_i2c->base_address, SMBALERT_NO_CONTROL, 0x01u);\r
+\r
+\r
+ HAL_restore_interrupts( saved_psr );\r
+}\r
+\r
+/*------------------------------------------------------------------------------\r
+ * I2C_get_irq_status()\r
+ * See "i2c.h" for details of how to use this function.\r
+ */\r
+uint8_t I2C_get_irq_status\r
+(\r
+ i2c_instance_t * this_i2c\r
+)\r
+{\r
+ uint8_t status ;\r
+ uint8_t irq_type = I2C_NO_IRQ ;\r
+\r
+ status = HAL_get_8bit_reg(this_i2c->base_address, SMBUS);\r
+\r
+ if( status & (uint8_t)SMBALERT_NI_STATUS_MASK )\r
+ {\r
+ irq_type |= I2C_SMBALERT_IRQ ;\r
+ }\r
+\r
+ if( status & (uint8_t)SMBSUS_NI_STATUS_MASK )\r
+ {\r
+ irq_type |= I2C_SMBSUS_IRQ ;\r
+ }\r
+\r
+ status = HAL_get_8bit_reg(this_i2c->base_address, CONTROL);\r
+\r
+ if( status & (uint8_t)SI_MASK )\r
+ {\r
+ irq_type |= I2C_INTR_IRQ ;\r
+ }\r
+ return(irq_type);\r
+}\r
+\r
+/*------------------------------------------------------------------------------\r
+ * I2C_set_slave_addr2()\r
+ * See "i2c.h" for details of how to use this function.\r
+ */\r
+void I2C_set_user_data\r
+(\r
+ i2c_instance_t * this_i2c,\r
+ void * p_user_data\r
+)\r
+{\r
+ this_i2c->p_user_data = p_user_data ;\r
+}\r
+\r
+/*------------------------------------------------------------------------------\r
+ * I2C_get_user_data()\r
+ * See "i2c.h" for details of how to use this function.\r
+ */\r
+void * I2C_get_user_data\r
+(\r
+ i2c_instance_t * this_i2c\r
+)\r
+{\r
+ return( this_i2c->p_user_data);\r
+}\r
+\r
+#ifdef __cplusplus\r
+}\r
+#endif\r
+\r
--- /dev/null
+/*******************************************************************************\r
+ * (c) Copyright 2009-2015 Microsemi SoC Products Group. All rights reserved.\r
+ * \r
+ * CoreI2C software driver Application Programming Interface.\r
+ * This file contains defines and function declarations allowing to interface\r
+ * with the CoreI2C software driver.\r
+ * \r
+ * SVN $Revision: 7984 $\r
+ * SVN $Date: 2015-10-12 12:07:40 +0530 (Mon, 12 Oct 2015) $\r
+ */\r
+/*=========================================================================*//**\r
+ @mainpage CoreI2C Bare Metal Driver.\r
+ The CoreI2C bare metal software driver supports I2C master and slave\r
+ operations.\r
+\r
+ @section intro_sec Introduction\r
+ The CoreI2C driver provides a set of functions for controlling the Microsemi\r
+ CoreI2C hardware IP. The driver supports up to 16 separate I2C channels per\r
+ CoreI2C instance, with common slave address settings shared between channels\r
+ on a device.\r
+ \r
+ Optional features of the CoreI2C allow it operate with I2C based protocols\r
+ such as System Management Bus (SMBus), Power Management Bus (PMBus) and\r
+ Intelligent Platform Management Interface (IPMI). This driver provides support\r
+ for these features when enabled in the CoreI2C IP.\r
+ \r
+ The major features provided by CoreI2C driver are:\r
+ - Support for configuring the I2C channels of each CoreI2C peripheral.\r
+ - I2C master operations.\r
+ - I2C slave operations.\r
+ - SMBus related operations.\r
+\r
+ This driver can be used as part of a bare metal system where no operating \r
+ system is available. The driver can be adapted for use as part of an \r
+ operating system, but the implementation of the adaptation layer between the \r
+ driver and the operating system's driver model is outside the scope of this \r
+ driver.\r
+ \r
+ @section hw_dependencies Hardware Flow Dependencies\r
+ Your application software should configure the CoreI2C driver through\r
+ calls to the I2C_init() function for each CoreI2C instance in the\r
+ hardware design. The configuration parameters include the CoreI2C hardware\r
+ instance base address and other runtime parameters, such as the I2C serial\r
+ clock frequency and I2C device address.\r
+ \r
+ Once channel 0 of a CoreI2C peripheral has been initialized via I2C_init(),\r
+ any additional channels present should be configured by calling\r
+ I2C_channel_init() for each of the remaining channels.\r
+ \r
+ No CoreI2C hardware configuration parameters are used by the driver, apart\r
+ from the CoreI2C hardware instance base address. Hence, no additional\r
+ configuration files are required to use the driver. \r
+ \r
+ Interrupt Control\r
+ The CoreI2C driver has to enable and disable the generation of interrupts by\r
+ CoreI2C at various times when it is operating. This enabling and disabling of\r
+ interrupts must be done through the system\92s interrupt controller. For that\r
+ reason, the method of controlling the CoreI2C interrupt is system specific\r
+ and it is necessary to customize the I2C_enable_irq() and I2C_disable_irq()\r
+ functions. These functions are found in the file i2c_interrupt.c. Their\r
+ default implementation fires an assertion to attract attention to the fact\r
+ that these functions must be modified.\r
+ \r
+ The implementation of the I2C_enable_irq() function should permit interrupts\r
+ generated by a CoreI2C instance to interrupt the processor. The implementation\r
+ of the I2C_disable_irq() function should prevent interrupts generated by a\r
+ CoreI2C instance from interrupting the processor. Please refer to the provided\r
+ example projects for a working implementation of these functions.\r
+ \r
+ The function I2C_register_write_handler() is used to register a write handler\r
+ function with the CoreI2C driver that it calls on completion of an I2C write\r
+ transaction by the CoreI2C slave. It is your responsibility to create and\r
+ register the implementation of this handler function that processes or\r
+ trigger the processing of the received data.\r
+ \r
+ The SMBSUS and SMBALERT interrupts are related to the SMBus interface and are\r
+ enabled and disabled through I2C_enable_smbus_irq() and \r
+ I2C_disable_smbus_irq() respectively. It is your responsibility to create\r
+ interrupt handler functions in your application to get the desired response\r
+ for the SMBus interrupts.\r
+\r
+ Note: You must include the path to any application header files that are\r
+ included in the i2c_interrupt.c file, as an include path in your\r
+ project\92s compiler settings. The details of how to do this will depend\r
+ on your development software.\r
+\r
+ SMBus Logic options\r
+ SMBus related APIs will not have any effect if in CoreI2C hardware\r
+ configuration "Generate SMBus Logic" is not enabled. The APIs which will not\r
+ give desired results in case SMBus Logic is disabled are:\r
+ \r
+ I2C_smbus_init()\r
+ I2C_reset_smbus()\r
+ I2C_enable_smbus_irq()\r
+ I2C_disable_smbus_irq()\r
+ I2C_suspend_smbus_slave()\r
+ I2C_resume_smbus_slave()\r
+ I2C_set_smsbus_alert()\r
+ I2C_clear_smsbus_alert()\r
+ I2C_get_irq_status() \r
+\r
+ Fixed Baud Rate Values\r
+ The serial clock frequency parameter passed to the I2C_init() and \r
+ I2C_channel_init() functions may not have any effect if fixed values were\r
+ selected for Baud rate in the hardware configuration of CoreI2C. When fixed\r
+ values are selected for these baud rates, the driver cannot overwrite\r
+ the fixed values.\r
+\r
+ Fixed Slave Address Options Values\r
+ The primary slave address parameter passed to the I2C_init() function, and\r
+ secondary address value passed to the I2C_set_slave_second_addr() function,\r
+ may not have the desired effect if fixed values were selected for the slave 0\r
+ address and slave 1 address respectively. Proper operation of this version of\r
+ the driver requires the slave addresses to be programmable.\r
+\r
+ @section theory_op Theory of Operation\r
+ The CoreI2C software driver is designed to allow the control of multiple\r
+ instances of CoreI2C with one or more I2C channels. Each channel in an\r
+ instance of CoreI2C in the hardware design is associated with a single \r
+ instance of the i2c_instance_t structure in the software. You must allocate\r
+ memory for one unique i2c_instance_t structure instance for each channel of\r
+ each CoreI2C hardware instance. The contents of these data structures are\r
+ initialised during calls to I2C_init() and if necessary I2C_channel_init().\r
+ A pointer to the structure is passed to subsequent driver functions in order\r
+ to identify the CoreI2C hardware instance and channel you wish to perform the\r
+ requested operation.\r
+\r
+ Note: Do not attempt to directly manipulate the contents of i2c_instance_t\r
+ structures. These structures are only intended to be modified by the driver\r
+ functions.\r
+\r
+ The CoreI2C driver functions are grouped into the following categories:\r
+ - Initialization and configuration functions\r
+ - Interrupt control\r
+ - I2C slave addressing functions\r
+ - I2C master operations functions to handle write, read and write-read \r
+ transactions\r
+ - I2C slave operations functions to handle write, read and write-read \r
+ transactions\r
+ - Mixed master-slave operations \r
+ - SMBus interface configuration and control.\r
+ \r
+ Initialization and Configuration\r
+ The CoreI2C device is first initialized through a call to the I2C_init()\r
+ function. Since each CoreI2C peripheral supports up to 16 channels, an\r
+ additional function, I2C_channel_init(), is required to initialize the\r
+ remaining channels with their own data structures.\r
+\r
+ I2C_init() initializes channel 0 of a CoreI2C and the i2c_instance_t for\r
+ channel 0 acts as the basis for further channel initialization as the\r
+ hardware base address and I2C serial address are same across all the\r
+ channels. I2C_init() must be called before any other I2C driver function\r
+ calls. The I2C_init() call for each CoreI2C takes the I2C serial address\r
+ assigned to the I2C and the serial clock divider to be used to generate its\r
+ I2C clock as configuration parameters. \r
+ \r
+ I2C_channel_init() takes as input parameters a pointer to the CoreI2C \r
+ i2c_instance_t which has been initialized via I2C_init() and a pointer to a\r
+ separate i2c_instance_t which represents this new channel. Another input\r
+ parameter which is required by this function is serial clock divider which\r
+ generates its I2C clock. \r
+ \r
+ Interrupt Control\r
+ The CoreI2C driver is interrupt driven and it uses each channels INT\r
+ interrupt to drive the state machine which is at the heart of the driver.\r
+ The application is responsible for providing the link between the interrupt\r
+ generating hardware and the CoreI2C interrupt handler and must ensure that\r
+ the I2C_isr() function is called with the correct i2c_instance_t structure\r
+ pointer for the CoreI2C channel initiating the interrupt.\r
+ \r
+ The driver enables and disables the generation of INT interrupts by CoreI2C\r
+ at various times when it is operating through the user supplied\r
+ I2C_enable_irq() and I2C_disable_irq() functions. \r
+ \r
+ The function I2C_register_write_handler() is used to register a write\r
+ handler function with the CoreI2C driver which is called on completion\r
+ of an I2C write transaction by the CoreI2C slave. It is the user\r
+ applications responsibility to create and register the implementation of\r
+ this handler function that processes or triggers the processing of the\r
+ received data. \r
+ \r
+ The other two interrupt sources in the CoreI2C, are related to SMBus\r
+ operation and are enabled and disabled through I2C_enable_smbus_irq() and\r
+ I2C_disable_smbus_irq() respectively. Due to the application specific\r
+ nature of the response to SMBus interrupts, you must design interrupt\r
+ handler functions in the application to get the desired behaviour for\r
+ SMBus related interrupts.\r
+ \r
+ If enabled, the SMBA_INT signal from the CoreI2C is asserted if an\r
+ SMBALERT condition is signalled on the SMBALERT_NI input for the channel.\r
+ \r
+ If enabled, the SMBS_INT signal from the CoreI2C is asserted if an\r
+ SMBSUSPEND condition is signalled on the SMBSUS_NI input for the channel.\r
+\r
+ I2C slave addressing functions\r
+ A CoreI2C peripheral can respond to three slave addresses:\r
+ - Slave address 0 - This is the primary slave address which is used for\r
+ accessing a CoreI2C channel when it acts as a slave in\r
+ I2C transactions. You must configure the primary slave\r
+ address via I2C_init().\r
+ \r
+ - Slave address 1 - This is the secondary slave address which might be\r
+ required in certain application specific scenarios.\r
+ The secondary slave address can be configured via\r
+ I2C_set_slave_second_addr() and disabled via \r
+ I2C_disable_slave_second_addr().\r
+ \r
+ - General call address - A CoreI2C slave can be configured to respond to\r
+ a broadcast command by a master transmitting the\r
+ general call address of 0x00. Use the I2C_set_gca()\r
+ function to enable the slave to respond to the general\r
+ call address. If the CoreI2C slave is not required to\r
+ respond to the general call address, disable this\r
+ address by calling I2C_clear_gca().\r
+\r
+ Note: All channels on a CoreI2C instance share the same slave address logic.\r
+ This means that they cannot have separate slave addresses and rely on\r
+ the separate physical I2C bus connections to distinguish them.\r
+ \r
+ Transaction Types\r
+ The I2C driver is designed to handle three types of I2C transaction:\r
+ Write transactions\r
+ Read transactions\r
+ Write-read transactions\r
+ \r
+ Write transaction\r
+ The master I2C device initiates a write transaction by sending a START bit\r
+ as soon as the bus becomes free. The START bit is followed by the 7-bit\r
+ serial address of the target slave device followed by the read/write bit\r
+ indicating the direction of the transaction. The slave acknowledges the\r
+ receipt of it's address with an acknowledge bit. The master sends data one\r
+ byte at a time to the slave, which must acknowledge receipt of each byte\r
+ for the next byte to be sent. The master sends a STOP bit to complete the\r
+ transaction. The slave can abort the transaction by replying with a \r
+ non-acknowledge bit instead of an acknowledge.\r
+ \r
+ The application programmer can choose not to send a STOP bit at the end of\r
+ the transaction causing the next transaction to begin with a repeated \r
+ START bit.\r
+ \r
+ Read transaction\r
+ The master I2C device initiates a read transaction by sending a START bit\r
+ as soon as the bus becomes free. The START bit is followed by the 7-bit\r
+ serial address of the target slave device followed by the read/write bit\r
+ indicating the direction of the transaction. The slave acknowledges\r
+ receipt of it's slave address with an acknowledge bit. The slave sends\r
+ data one byte at a time to the master, which must acknowledge receipt of\r
+ each byte for the next byte to be sent. The master sends a non-acknowledge\r
+ bit following the last byte it wishes to read followed by a STOP bit.\r
+ \r
+ The application programmer can choose not to send a STOP bit at the end of\r
+ the transaction causing the next transaction to begin with a repeated \r
+ START bit.\r
+ \r
+ Write-read transaction\r
+ The write-read transaction is a combination of a write transaction\r
+ immediately followed by a read transaction. There is no STOP bit between\r
+ the write and read phases of a write-read transaction. A repeated START\r
+ bit is sent between the write and read phases.\r
+ \r
+ Whilst the write handler is being executed, the slave holds the clock line\r
+ low to stretch the clock until the response is ready.\r
+ \r
+ The write-read transaction is typically used to send a command or offset\r
+ in the write transaction specifying the logical data to be transferred\r
+ during the read phase.\r
+ \r
+ The application programmer can choose not to send a STOP bit at the end of\r
+ the transaction causing the next transaction to begin with a repeated\r
+ START bit.\r
+\r
+ Master Operations\r
+ The application can use the I2C_write(), I2C_read() and I2C_write_read()\r
+ functions to initiate an I2C bus transaction. The application can then wait\r
+ for the transaction to complete using the I2C_wait_complete() function\r
+ or poll the status of the I2C transaction using the I2C_get_status()\r
+ function until it returns a value different from I2C_IN_PROGRESS. The\r
+ I2C_system_tick() function can be used to set a time base for the\r
+ I2C_wait_complete() function\92s time out delay.\r
+\r
+ Slave Operations\r
+ The configuration of the I2C driver to operate as an I2C slave requires\r
+ the use of the following functions:\r
+ I2C_set_slave_tx_buffer()\r
+ I2C_set_slave_rx_buffer()\r
+ I2C_set_slave_mem_offset_length()\r
+ I2C_register_write_handler()\r
+ I2C_enable_slave()\r
+ \r
+ Use of all functions is not required if the slave I2C does not need to support\r
+ all types of I2C read transactions. The subsequent sections list the functions\r
+ that must be used to support each transaction type. \r
+ \r
+ Responding to read transactions\r
+ The following functions are used to configure the CoreI2C driver to\r
+ respond to I2C read transactions:\r
+ I2C_set_slave_tx_buffer()\r
+ I2C_enable_slave()\r
+ \r
+ The function I2C_set_slave_tx_buffer() specifies the data buffer that\r
+ will be transmitted when the I2C slave is the target of an I2C read\r
+ transaction. It is then up to the application to manage the content of\r
+ that buffer to control the data that will be transmitted to the I2C\r
+ master as a result of the read transaction.\r
+ \r
+ The function I2C_enable_slave() enables the I2C hardware instance\r
+ to respond to I2C transactions. It must be called after the I2C driver\r
+ has been configured to respond to the required transaction types.\r
+\r
+ Responding to write transactions\r
+ The following functions are used to configure the I2C driver to respond\r
+ to I2C write transactions:\r
+ I2C_set_slave_rx_buffer()\r
+ I2C_register_write_handler()\r
+ I2C_enable_slave()\r
+ \r
+ The function I2C_set_slave_rx_buffer() specifies the data buffer that\r
+ will be used to store the data received by the I2C slave when it is the\r
+ target an I2C write transaction.\r
+ \r
+ The function I2C_register_write_handler() specifies the handler function\r
+ that must be called on completion of the I2C write transaction. It is this\r
+ handler function that processes or triggers the processing of the received\r
+ data.\r
+ \r
+ The function I2C_enable_slave() enables the I2C hardware instance\r
+ to respond to I2C transactions. It must be called after the I2C driver\r
+ has been configured to respond to the required transaction types.\r
+\r
+ Responding to write-read transactions\r
+ The following functions are used to configure the CoreI2C driver to \r
+ respond to write-read transactions:\r
+ I2C_set_slave_mem_offset_length()\r
+ I2C_set_slave_tx_buffer()\r
+ I2C_set_slave_rx_buffer()\r
+ I2C_register_write_handler()\r
+ I2C_enable_slave()\r
+ \r
+ The function I2C_set_slave_mem_offset_length() specifies the number of\r
+ bytes expected by the I2C slave during the write phase of the write-read\r
+ transaction.\r
+ \r
+ The function I2C_set_slave_tx_buffer() specifies the data that will be\r
+ transmitted to the I2C master during the read phase of the write-read\r
+ transaction. The value received by the I2C slave during the write phase of\r
+ the transaction will be used as an index into the transmit buffer\r
+ specified by this function to decide which part of the transmit buffer\r
+ will be transmitted to the I2C master as part of the read phase of the\r
+ write-read transaction. \r
+ \r
+ The function I2C_set_slave_rx_buffer() specifies the data buffer that\r
+ will be used to store the data received by the I2C slave during the write\r
+ phase of the write-read transaction. This buffer must be at least large\r
+ enough to accommodate the number of bytes specified through the\r
+ I2C_set_slave_mem_offset_length() function.\r
+ \r
+ The function I2C_register_write_handler() can optionally be used to\r
+ specify a handler function that is called on completion of the write phase\r
+ of the I2C write-read transaction. If a handler function is registered, it\r
+ is responsible for processing the received data in the slave receive\r
+ buffer and populating the slave transmit buffer with the data that will be\r
+ transmitted to the I2C master as part of the read phase of the write-read\r
+ transaction.\r
+ \r
+ The function I2C_enable_slave() enables the CoreI2C hardware instance to \r
+ respond to I2C transactions. It must be called after the CoreI2C driver\r
+ has been configured to respond to the required transaction types.\r
+\r
+ Mixed Master-Slave Operations\r
+ The CoreI2C device supports mixed master and slave operations. If the \r
+ CoreI2C slave has a transaction in progress and your application attempts to\r
+ begin a master mode transaction, the CoreI2C driver queu3es the master mode\r
+ transaction until the bus is released and the CoreI2C can switch to master\r
+ mode and acquire the bus. The CoreI2C master then starts the previously\r
+ queued master transaction.\r
+ \r
+ SMBus Control\r
+ The CoreI2C driver enables the CoreI2C peripheral\92s SMBus functionality\r
+ using the I2C_smbus_init() function.\r
+ \r
+ The I2C_suspend_smbus_slave() function is used, with a master mode CoreI2C,\r
+ to force slave devices on the SMBus to enter their power-down/suspend mode.\r
+ The I2C_resume_smbus_slave() function is used to end the suspend operation\r
+ on the SMBus.\r
+ \r
+ The I2C_reset_smbus() function is used, with a master mode CoreI2C, to force\r
+ all devices on the SMBus to reset their SMBUs interface.\r
+ \r
+ The I2C_set_smsbus_alert() function is used, by a slave mode CoreI2C, to\r
+ force communication with the SMBus master. Once communications with the\r
+ master is initiated, the I2C_clear_smsbus_alert() function is used to clear\r
+ the alert condition.\r
+ \r
+ The I2C_enable_smbus_irq() and I2C_disable_smbus_irq() functions are used to\r
+ enable and disable the SMBSUS and SMBALERT SMBus interrupts.\r
+\r
+ *//*=========================================================================*/\r
+\r
+#ifndef CORE_I2C_H_\r
+#define CORE_I2C_H_\r
+\r
+#include "cpu_types.h"\r
+#ifdef __cplusplus\r
+extern "C" {\r
+#endif \r
+\r
+/*-------------------------------------------------------------------------*//**\r
+ The I2C_RELEASE_BUS constant is used to specify the options parameter to\r
+ functions I2C_read(), I2C_write() and I2C_write_read() to indicate\r
+ that a STOP bit must be generated at the end of the I2C transaction to release\r
+ the bus.\r
+ */\r
+#define I2C_RELEASE_BUS 0x00u\r
+\r
+/*-------------------------------------------------------------------------*//**\r
+ The I2C_HOLD_BUS constant is used to specify the options parameter to\r
+ functions I2C_read(), I2C_write() and I2C_write_read() to indicate\r
+ that a STOP bit must not be generated at the end of the I2C transaction in\r
+ order to retain the bus ownership. This causes the next transaction to\r
+ begin with a repeated START bit and no STOP bit between the transactions.\r
+ */\r
+#define I2C_HOLD_BUS 0x01u\r
+\r
+/*-------------------------------------------------------------------------*//**\r
+ The following constants specify the interrupt identifier number which will be\r
+ solely used by driver API. This has nothing to do with hardware interrupt line.\r
+ I2C_INT_IRQ is the primary interrupt signal which drives the state machine\r
+ of the CoreI2C driver. The I2C_SMBALERT_IRQ and I2C_SMBUS_IRQ are used by\r
+ SMBus interrupt enable and disable functions. These IRQ numbers are also used\r
+ by I2C_get_irq_status().\r
+ */\r
+#define I2C_NO_IRQ 0x00u\r
+#define I2C_SMBALERT_IRQ 0x01u\r
+#define I2C_SMBSUS_IRQ 0x02u\r
+#define I2C_INTR_IRQ 0x04u\r
+\r
+/*-------------------------------------------------------------------------*//**\r
+ The I2C_NO_TIMEOUT constant is used as parameter to the I2C_wait_complete()\r
+ function to indicate that the wait for completion of the transaction should\r
+ not time out.\r
+ */\r
+#define I2C_NO_TIMEOUT 0u\r
+\r
+/*-------------------------------------------------------------------------*//**\r
+ The i2c_channel_number_t type is used to specify the channel number of a\r
+ CoreI2C instance.\r
+ */\r
+typedef enum i2c_channel_number {\r
+ I2C_CHANNEL_0 = 0u,\r
+ I2C_CHANNEL_1,\r
+ I2C_CHANNEL_2,\r
+ I2C_CHANNEL_3,\r
+ I2C_CHANNEL_4,\r
+ I2C_CHANNEL_5,\r
+ I2C_CHANNEL_6,\r
+ I2C_CHANNEL_7,\r
+ I2C_CHANNEL_8,\r
+ I2C_CHANNEL_9,\r
+ I2C_CHANNEL_10,\r
+ I2C_CHANNEL_11,\r
+ I2C_CHANNEL_12,\r
+ I2C_CHANNEL_13,\r
+ I2C_CHANNEL_14,\r
+ I2C_CHANNEL_15,\r
+ I2C_MAX_CHANNELS = 16u\r
+} i2c_channel_number_t;\r
+\r
+/*-------------------------------------------------------------------------*//**\r
+ The i2c_clock_divider_t type is used to specify the divider to be applied\r
+ to the I2C PCLK or BCLK signal in order to generate the I2C clock.\r
+ The I2C_BCLK_DIV_8 value selects a clock frequency based on division of BCLK,\r
+ all other values select a clock frequency based on division of PCLK.\r
+ */\r
+typedef enum i2c_clock_divider {\r
+ I2C_PCLK_DIV_256 = 0u,\r
+ I2C_PCLK_DIV_224,\r
+ I2C_PCLK_DIV_192,\r
+ I2C_PCLK_DIV_160,\r
+ I2C_PCLK_DIV_960,\r
+ I2C_PCLK_DIV_120,\r
+ I2C_PCLK_DIV_60,\r
+ I2C_BCLK_DIV_8\r
+} i2c_clock_divider_t;\r
+\r
+/*-------------------------------------------------------------------------*//**\r
+ The i2c_status_t type is used to report the status of I2C transactions.\r
+ */\r
+typedef enum i2c_status\r
+{\r
+ I2C_SUCCESS = 0u,\r
+ I2C_IN_PROGRESS,\r
+ I2C_FAILED,\r
+ I2C_TIMED_OUT\r
+} i2c_status_t;\r
+\r
+/*-------------------------------------------------------------------------*//**\r
+ The i2c_slave_handler_ret_t type is used by slave write handler functions\r
+ to indicate whether or not the received data buffer should be released.\r
+ */\r
+typedef enum i2c_slave_handler_ret {\r
+ I2C_REENABLE_SLAVE_RX = 0u,\r
+ I2C_PAUSE_SLAVE_RX = 1u\r
+} i2c_slave_handler_ret_t;\r
+\r
+typedef struct i2c_instance i2c_instance_t ;\r
+\r
+/*-------------------------------------------------------------------------*//**\r
+ Slave write handler functions prototype.\r
+ ------------------------------------------------------------------------------\r
+ This defines the function prototype that must be followed by I2C slave write\r
+ handler functions. These functions are registered with the CoreI2C driver\r
+ through the I2C_register_write_handler() function.\r
+\r
+ Declaring and Implementing Slave Write Handler Functions:\r
+ Slave write handler functions should follow the following prototype:\r
+ i2c_slave_handler_ret_t write_handler\r
+ ( \r
+ i2c_instance_t *instance, uint8_t * data, uint16_t size \r
+ );\r
+\r
+ The instance parameter is a pointer to the i2c_instance_t for which this\r
+ slave write handler has been declared.\r
+ \r
+ The data parameter is a pointer to a buffer (received data buffer) holding\r
+ the data written to the I2C slave.\r
+ \r
+ Defining the macro INCLUDE_SLA_IN_RX_PAYLOAD causes the driver to insert the\r
+ actual address used to access the slave as the first byte in the buffer.\r
+ This allows applications tailor their response based on the actual address\r
+ used to access the slave (primary address, secondary address or GCA).\r
+ \r
+ The size parameter is the number of bytes held in the received data buffer.\r
+ Handler functions must return one of the following values:\r
+ I2C_REENABLE_SLAVE_RX\r
+ I2C_PAUSE_SLAVE_RX.\r
+ \r
+ If the handler function returns I2C_REENABLE_SLAVE_RX, the driver releases\r
+ the received data buffer and allows further I2C write transactions to the\r
+ I2C slave to take place.\r
+ \r
+ If the handler function returns I2C_PAUSE_SLAVE_RX, the I2C slave responds\r
+ to subsequent write requests with a non-acknowledge bit (NACK), until the\r
+ received data buffer content has been processed by some other part of the\r
+ software application.\r
+ \r
+ A call to I2C_enable_slave() is required at some point after returning\r
+ I2C_PAUSE_SLAVE_RX in order to release the received data buffer so it can\r
+ be used to store data received by subsequent I2C write transactions.\r
+ */\r
+typedef i2c_slave_handler_ret_t (*i2c_slave_wr_handler_t)(i2c_instance_t *instance, uint8_t *, uint16_t );\r
+\r
+\r
+/*-------------------------------------------------------------------------*//**\r
+ i2c_instance_t\r
+ ------------------------------------------------------------------------------\r
+ This structure is used to identify the various CoreI2C hardware instances in\r
+ your system and the I2C channels within them. Your application software should\r
+ declare one instance of this structure for each channel of each instance of\r
+ CoreI2C in your system. The functions I2C_init() and I2C_channel_init() \r
+ initialize this structure depending on whether it is channel 0 or one of the\r
+ additional channels respectively. A pointer to an initialized instance of the\r
+ structure should be passed as the first parameter to the CoreI2C driver\r
+ functions, to identify which CoreI2C hardware instance and channel should\r
+ perform the requested operation.\r
+ \r
+ The contents of this data structure should not be modified or used outside of\r
+ the CoreI2C driver. Software using the CoreI2C driver should only need to \r
+ create one single instance of this data structure for each channel of each \r
+ CoreI2C hardware instance in the system then pass a pointer to these data\r
+ structures with each call to the CoreI2C driver in order to identify the\r
+ CoreI2C hardware instance it wishes to use.\r
+ */\r
+struct i2c_instance\r
+{\r
+ addr_t base_address;\r
+ uint_fast8_t ser_address;\r
+\r
+ /* Transmit related info:*/\r
+ uint_fast8_t target_addr;\r
+\r
+ /* Current transaction type (WRITE, READ, RANDOM_READ)*/\r
+ uint8_t transaction;\r
+ \r
+ uint_fast16_t random_read_addr;\r
+\r
+ uint8_t options;\r
+ \r
+ /* Master TX INFO: */\r
+ const uint8_t * master_tx_buffer;\r
+ uint_fast16_t master_tx_size;\r
+ uint_fast16_t master_tx_idx;\r
+ uint_fast8_t dir;\r
+ \r
+ /* Master RX INFO: */\r
+ uint8_t * master_rx_buffer;\r
+ uint_fast16_t master_rx_size;\r
+ uint_fast16_t master_rx_idx;\r
+\r
+ /* Master Status */\r
+ volatile i2c_status_t master_status;\r
+ uint32_t master_timeout_ms;\r
+\r
+ /* Slave TX INFO */\r
+ const uint8_t * slave_tx_buffer;\r
+ uint_fast16_t slave_tx_size;\r
+ uint_fast16_t slave_tx_idx;\r
+ \r
+ /* Slave RX INFO */\r
+ uint8_t * slave_rx_buffer;\r
+ uint_fast16_t slave_rx_size;\r
+ uint_fast16_t slave_rx_idx;\r
+ /* Slave Status */\r
+ volatile i2c_status_t slave_status;\r
+ \r
+ /* Slave data: */\r
+ uint_fast8_t slave_mem_offset_length;\r
+ i2c_slave_wr_handler_t slave_write_handler;\r
+ uint8_t is_slave_enabled;\r
+ \r
+ /* user specific data */\r
+ void *p_user_data ;\r
+\r
+ /* I2C bus status */\r
+ uint8_t bus_status;\r
+\r
+ /* Is transaction pending flag */\r
+ uint8_t is_transaction_pending;\r
+\r
+ /* I2C Pending transaction */\r
+ uint8_t pending_transaction;\r
+};\r
+\r
+/*-------------------------------------------------------------------------*//**\r
+ I2C initialization routine.\r
+ ------------------------------------------------------------------------------\r
+ The I2C_init() function is used to configure channel 0 of a CoreI2C instance.\r
+ It sets the base hardware address which is used to locate the CoreI2C instance\r
+ in memory and also used internally by I2C_channel_init() to calculate the\r
+ register addresses for any additional channels. The slave serial address set\r
+ is shared by all channels on a CoreI2C instance. \r
+ \r
+ If only one channel is configured in a CoreI2C, the address of the \r
+ i2c_instance_t used in I2C_Init() will also be used in subsequent calls to the\r
+ CoreI2C driver functions. If more than one channel is configured in the\r
+ CoreI2C, I2C_channel_init() will be called after I2C_init(), which initializes\r
+ the i2c_instance_t data structure for a specific channel.\r
+ ------------------------------------------------------------------------------\r
+ @param this_i2c:\r
+ Pointer to the i2c_instance_t data structure which will hold all data\r
+ related to channel 0 of the CoreI2C instance being initialized. A pointer\r
+ to this structure will be used in all subsequent calls to CoreI2C driver\r
+ functions which are to operate on channel 0 of this CoreI2C instance.\r
+ \r
+ @param base_address:\r
+ Base address in the processor's memory map of the registers of the CoreI2C\r
+ instance being initialized.\r
+ \r
+ @param ser_address:\r
+ This parameter sets the primary I2C serial address (SLAVE0 address) for the\r
+ CoreI2C being initialized. It is the principal I2C bus address to which the\r
+ CoreI2C instance will respond. CoreI2C can operate in master mode or slave\r
+ mode and the serial address is significant only in the case of I2C slave\r
+ mode. In master mode, CoreI2C does not require a serial address and the\r
+ value of this parameter is not important. If you do not intend to use the\r
+ CoreI2C device in slave mode, then any dummy slave address value can be\r
+ provided to this parameter. However, in systems where the CoreI2C may be\r
+ expected to switch from master mode to slave mode, it is advisable to\r
+ initialize the CoreI2C device with a valid serial slave address.\r
+ \r
+ You need to call the I2C_init() function whenever it is required to change \r
+ the primary slave address as there is no separate function to set the\r
+ primary slave address of the I2C device. The serial address being\r
+ initialized through this function is basically the primary slave address or\r
+ slave address0. I2C_set_slave_second_addr() can be used to set the\r
+ secondary slave address or slave address 1.\r
+ Note : ser_address parameter does not have any affect if fixed slave \r
+ address is enabled in CoreI2C hardware design. CoreI2C will \r
+ be always addressed with the hardware configured fixed slave\r
+ address.\r
+ Note : ser_address parameter will not have any affect if the CoreI2C\r
+ instance is only used in master mode.\r
+\r
+ @param ser_clock_speed:\r
+ This parameter sets the I2C serial clock frequency. It selects the divider\r
+ that will be used to generate the serial clock from the APB PCLK or from\r
+ the BCLK. It can be one of the following:\r
+ I2C_PCLK_DIV_256\r
+ I2C_PCLK_DIV_224\r
+ I2C_PCLK_DIV_192\r
+ I2C_PCLK_DIV_160\r
+ I2C_PCLK_DIV_960\r
+ I2C_PCLK_DIV_120\r
+ I2C_PCLK_DIV_60\r
+ I2C_BCLK_DIV_8\r
+ Note: serial_clock_speed value will have no affect if Fixed baud rate is \r
+ enabled in CoreI2C hardware instance configuration dialogue window. \r
+ The fixed baud rate divider value will override the value\r
+ passed as parameter in this function.\r
+ Note: serial_clock_speed value is not critical for devices that only operate\r
+ as slaves and can be set to any of the above values. \r
+\r
+ @return none. \r
+ \r
+ Example:\r
+ @code\r
+ #define COREI2C_BASE_ADDR 0xC0000000u\r
+ #define COREI2C_SER_ADDR 0x10u\r
+\r
+ i2c_instance_t g_i2c_inst;\r
+\r
+ void system_init( void )\r
+ {\r
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, COREI2C_SER_ADDR,\r
+ I2C_PCLK_DIV_256 );\r
+ }\r
+ @endcode\r
+ */\r
+void I2C_init\r
+(\r
+ i2c_instance_t * this_i2c,\r
+ addr_t base_address,\r
+ uint8_t ser_address,\r
+ i2c_clock_divider_t ser_clock_speed\r
+);\r
+\r
+/*-------------------------------------------------------------------------*//**\r
+ I2C channel initialization routine.\r
+ ------------------------------------------------------------------------------\r
+ The I2C_channel_init() function initializes and configures hardware and data\r
+ structures of one of the additional channels of a CoreI2C instance.\r
+ I2C_init() must be called before calling this function to set the CoreI2C\r
+ instance hardware base address and I2C serial address. I2C_channel_init() also\r
+ initializes I2C serial clock divider to set the serial clock baud rate. \r
+ The pointer to data structure i2c_instance_t used for a particular channel\r
+ will be used as an input parameter to subsequent CoreI2C driver functions\r
+ which operate on this channel.\r
+ ------------------------------------------------------------------------------\r
+ @param this_i2c_channel\r
+ Pointer to the i2c_instance_t data structure holding all data related to the\r
+ CoreI2C channel being initialized. A pointer to the same data structure will\r
+ be used in subsequent calls to the CoreI2C driver functions in order to\r
+ identify the CoreI2C channel instance that should perform the operation \r
+ implemented by the called driver function.\r
+\r
+ @param this_i2c:\r
+ This is a pointer to an i2c_instance_t structure previously initialized by\r
+ I2C_init(). It holds information regarding the hardware base address and\r
+ I2C serial address for the CoreI2C containing the channel to be\r
+ initialized. This information is required by I2C_channel_init() to\r
+ initialize the i2c_instance_t structure pointed to by this_i2c_channel as\r
+ all channels in a CoreI2C instance share the same base address and serial\r
+ address. It is very important that the i2c_instance_t structure pointed to\r
+ by this_i2c has been previously initialized with a call to I2C_init().\r
+ \r
+ @param channel_number:\r
+ This parameter of type i2c_channel_number_t identifies the channel to be\r
+ initialized.\r
+\r
+ @param ser_clock_speed:\r
+ This parameter sets the I2C serial clock frequency. It selects the divider\r
+ that will be used to generate the serial clock from the APB PCLK or from\r
+ the BCLK. It can be one of the following:\r
+ I2C_PCLK_DIV_256\r
+ I2C_PCLK_DIV_224\r
+ I2C_PCLK_DIV_192\r
+ I2C_PCLK_DIV_160\r
+ I2C_PCLK_DIV_960\r
+ I2C_PCLK_DIV_120\r
+ I2C_PCLK_DIV_60\r
+ I2C_BCLK_DIV_8\r
+ \r
+ Note: serial_clock_speed value will have no affect if Fixed baud rate is \r
+ enabled in CoreI2C hardware instance configuration dialogue window. \r
+ The fixed baud rate divider value will supersede the value \r
+ passed as parameter in this function.\r
+\r
+ Note: ser_clock_speed value is not critical for devices that only operate\r
+ as slaves and can be set to any of the above values. \r
+ @return none. \r
+ \r
+ Example:\r
+ @code\r
+ #define COREI2C_BASE_ADDR 0xC0000000u\r
+ #define COREI2C_SER_ADDR 0x10u\r
+ #define DATA_LENGTH 16u\r
+\r
+ i2c_instance_t g_i2c_inst;\r
+ i2c_instance_t g_i2c_channel_1_inst;\r
+\r
+ uint8_t tx_buffer[DATA_LENGTH];\r
+ uint8_t write_length = DATA_LENGTH;\r
+\r
+ void system_init( void )\r
+ {\r
+ uint8_t target_slave_addr = 0x12;\r
+ \r
+ // Initialize base CoreI2C instance\r
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, COREI2C_SER_ADDR,\r
+ I2C_PCLK_DIV_256 );\r
+ \r
+ // Initialize CoreI2C channel 1 with different clock speed\r
+ I2C_channel_init( &g_i2c_channel_1_inst, &g_i2c_inst, I2C_CHANNEL_1,\r
+ I2C_PCLK_DIV_224 );\r
+ \r
+ // Write data to Channel 1 of CoreI2C instance.\r
+ I2C_write( &g_i2c_channel_1_inst, target_slave_addr, tx_buffer,\r
+ write_length, I2C_RELEASE_BUS );\r
+ }\r
+ @endcode\r
+ \r
+*/\r
+void I2C_channel_init\r
+(\r
+ i2c_instance_t * this_i2c_channel,\r
+ i2c_instance_t * this_i2c,\r
+ i2c_channel_number_t channel_number,\r
+ i2c_clock_divider_t ser_clock_speed\r
+);\r
+\r
+/*------------------------------------------------------------------------------\r
+ CoreI2C interrupt service routine.\r
+ ------------------------------------------------------------------------------\r
+ The function I2C_isr is the CoreI2C interrupt service routine. User must\r
+ call this function from their application level CoreI2C interrupt handler\r
+ function. This function runs the I2C state machine based on previous and \r
+ current status.\r
+ ------------------------------------------------------------------------------\r
+ @param this_i2c:\r
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure\r
+ holding all data related to a specific CoreI2C channel. For example, if only\r
+ one channel is initialized, this data structure holds the information of \r
+ channel 0 of the instantiated CoreI2C hardware.\r
+ \r
+ @return none\r
+ \r
+ Example:\r
+ @code\r
+ \r
+ #define COREI2C_BASE_ADDR 0xC0000000u\r
+ #define COREINTERRUPT_BASE_ADDR 0xCC000000u\r
+ #define COREI2C_SER_ADDR 0x10u\r
+ #define I2C_IRQ_NB 2u\r
+ \r
+ i2c_instance_t g_i2c_inst;\r
+\r
+ void core_i2c_isr( void )\r
+ {\r
+ I2C_isr( &g_i2c_inst );\r
+ }\r
+ \r
+ void main( void )\r
+ {\r
+ CIC_init( COREINTERRUPT_BASE_ADDR );\r
+ NVIC_init();\r
+ CIC_set_irq_handler( I2C_IRQ_NB, core_i2c_isr );\r
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, COREI2C_SER_ADDR,\r
+ I2C_PCLK_DIV_256 );\r
+ NVIC_enable_interrupt( NVIC_IRQ_0 );\r
+ }\r
+ @endcode\r
+ */\r
+void I2C_isr\r
+(\r
+ i2c_instance_t * this_i2c\r
+);\r
+\r
+/*******************************************************************************\r
+ *******************************************************************************\r
+ * \r
+ * Master specific functions\r
+ * \r
+ * The following functions are only used within an I2C master's implementation.\r
+ */\r
+ \r
+/*-------------------------------------------------------------------------*//**\r
+ I2C master write function.\r
+ ------------------------------------------------------------------------------\r
+ This function initiates an I2C master write transaction. This function returns\r
+ immediately after initiating the transaction. The content of the write buffer\r
+ passed as parameter should not be modified until the write transaction\r
+ completes. It also means that the memory allocated for the write buffer should\r
+ not be freed or should not go out of scope before the write completes. You can\r
+ check for the write transaction completion using the I2C_status() function.\r
+ ------------------------------------------------------------------------------\r
+ @param this_i2c:\r
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure\r
+ holding all data related to a specific CoreI2C channel. For example, if only\r
+ one channel is initialized, this data structure holds the information of \r
+ channel 0 of the instantiated CoreI2C hardware.\r
+\r
+ @param serial_addr:\r
+ This parameter specifies the serial address of the target I2C device.\r
+ \r
+ @param write_buffer:\r
+ This parameter is a pointer to a buffer holding the data to be written to\r
+ the target I2C device.\r
+ Care must be taken not to release the memory used by this buffer before the\r
+ write transaction completes. For example, it is not appropriate to return\r
+ from a function allocating this buffer as an auto array variable before the\r
+ write transaction completes as this would result in the buffer's memory \r
+ being de-allocated from the stack when the function returns. This memory\r
+ could then be subsequently reused and modified causing unexpected data to \r
+ be written to the target I2C device.\r
+ \r
+ @param write_size:\r
+ Number of bytes held in the write_buffer to be written to the target I2C\r
+ device.\r
+ \r
+ @param options:\r
+ The options parameter is used to indicate if the I2C bus should be released\r
+ on completion of the write transaction. Using the I2C_RELEASE_BUS\r
+ constant for the options parameter causes a STOP bit to be generated at the\r
+ end of the write transaction causing the bus to be released for other I2C\r
+ devices to use. Using the I2C_HOLD_BUS constant as options parameter\r
+ prevents a STOP bit from being generated at the end of the write\r
+ transaction, preventing other I2C devices from initiating a bus transaction.\r
+ \r
+ @return none. \r
+ \r
+ Example:\r
+ @code\r
+ #define COREI2C_BASE_ADDR 0xC0000000u\r
+ #define COREI2C_DUMMY_ADDR 0x10u\r
+ #define DATA_LENGTH 16u\r
+\r
+ i2c_instance_t g_i2c_inst;\r
+\r
+ uint8_t tx_buffer[DATA_LENGTH];\r
+ uint8_t write_length = DATA_LENGTH; \r
+\r
+ void main( void )\r
+ {\r
+ uint8_t target_slave_addr = 0x12;\r
+ i2c_status_t status;\r
+ \r
+ // Initialize base CoreI2C instance\r
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, COREI2C_DUMMY_ADDR,\r
+ I2C_PCLK_DIV_256 );\r
+ \r
+ // Write data to Channel 0 of CoreI2C instance.\r
+ I2C_write( &g_i2c_inst, target_slave_addr, tx_buffer, write_length,\r
+ I2C_RELEASE_BUS );\r
+ \r
+ // Wait for completion and record the outcome\r
+ status = I2C_wait_complete( &g_i2c_inst, I2C_NO_TIMEOUT );\r
+ }\r
+ @endcode\r
+ */\r
+void I2C_write\r
+(\r
+ i2c_instance_t * this_i2c,\r
+ uint8_t serial_addr,\r
+ const uint8_t * write_buffer,\r
+ uint16_t write_size,\r
+ uint8_t options\r
+);\r
+\r
+/*-------------------------------------------------------------------------*//**\r
+ I2C master read.\r
+ ------------------------------------------------------------------------------\r
+ This function initiates an I2C master read transaction. This function returns\r
+ immediately after initiating the transaction.\r
+ The contents of the read buffer passed as parameter should not be modified\r
+ until the read transaction completes. It also means that the memory allocated\r
+ for the read buffer should not be freed or should not go out of scope before\r
+ the read completes. You can check for the read transaction completion using \r
+ the I2C_status() function.\r
+ ------------------------------------------------------------------------------\r
+ @param this_i2c:\r
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure\r
+ holding all data related to a specific CoreI2C channel. For example, if only\r
+ one channel is initialized, this data structure holds the information of \r
+ channel 0 of the instantiated CoreI2C hardware.\r
+ \r
+ @param serial_addr:\r
+ This parameter specifies the serial address of the target I2C device.\r
+ \r
+ @param read_buffer\r
+ This is a pointer to a buffer where the data received from the target device\r
+ will be stored.\r
+ Care must be taken not to release the memory used by this buffer before the\r
+ read transaction completes. For example, it is not appropriate to return\r
+ from a function allocating this buffer as an auto array variable before the\r
+ read transaction completes as this would result in the buffer's memory being\r
+ de-allocated from the stack when the function returns. This memory could\r
+ then be subsequently reallocated resulting in the read transaction\r
+ corrupting the newly allocated memory. \r
+\r
+ @param read_size:\r
+ This parameter specifies the number of bytes to read from the target device.\r
+ This size must not exceed the size of the read_buffer buffer.\r
+ \r
+ @param options:\r
+ The options parameter is used to indicate if the I2C bus should be released\r
+ on completion of the read transaction. Using the I2C_RELEASE_BUS\r
+ constant for the options parameter causes a STOP bit to be generated at the\r
+ end of the read transaction causing the bus to be released for other I2C\r
+ devices to use. Using the I2C_HOLD_BUS constant as options parameter\r
+ prevents a STOP bit from being generated at the end of the read transaction,\r
+ preventing other I2C devices from initiating a bus transaction.\r
+ \r
+ @return none. \r
+ \r
+ Example:\r
+ @code\r
+ #define COREI2C_BASE_ADDR 0xC0000000u\r
+ #define COREI2C_DUMMY_ADDR 0x10u\r
+ #define DATA_LENGTH 16u\r
+\r
+ i2c_instance_t g_i2c_inst;\r
+\r
+ uint8_t rx_buffer[DATA_LENGTH];\r
+ uint8_t read_length = DATA_LENGTH; \r
+\r
+ void main( void )\r
+ {\r
+ uint8_t target_slave_addr = 0x12;\r
+ i2c_status_t status;\r
+ \r
+ // Initialize base CoreI2C instance\r
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, COREI2C_DUMMY_ADDR,\r
+ I2C_PCLK_DIV_256 );\r
+ \r
+ // Read data from target slave Channel 0 of CoreI2C instance.\r
+ I2C_read( &g_i2c_inst, target_slave_addr, rx_buffer, read_length,\r
+ I2C_RELEASE_BUS );\r
+ \r
+ status = I2C_wait_complete( &g_i2c_inst, I2C_NO_TIMEOUT );\r
+ }\r
+ @endcode\r
+ */\r
+void I2C_read\r
+(\r
+ i2c_instance_t * this_i2c,\r
+ uint8_t serial_addr,\r
+ uint8_t * read_buffer,\r
+ uint16_t read_size,\r
+ uint8_t options\r
+);\r
+\r
+/*-------------------------------------------------------------------------*//**\r
+ I2C master write-read\r
+ ------------------------------------------------------------------------------\r
+ This function initiates an I2C write-read transaction where data is first\r
+ written to the target device before issuing a restart condition and changing\r
+ the direction of the I2C transaction in order to read from the target device.\r
+ \r
+ The same warnings about buffer allocation in I2C_write() and I2C_read() \r
+ apply to this function.\r
+ ------------------------------------------------------------------------------\r
+ @param this_i2c:\r
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure\r
+ holding all data related to a specific CoreI2C channel. For example, if only\r
+ one channel is initialized, this data structure holds the information of\r
+ channel 0 of the instantiated CoreI2C hardware.\r
+ \r
+ @param serial_addr:\r
+ This parameter specifies the serial address of the target I2C device.\r
+ \r
+ @param addr_offset:\r
+ This parameter is a pointer to the buffer containing the data that will be\r
+ sent to the slave during the write phase of the write-read transaction. This\r
+ data is typically used to specify an address offset specifying to the I2C\r
+ slave device what data it must return during the read phase of the\r
+ write-read transaction.\r
+ \r
+ @param offset_size:\r
+ This parameter specifies the number of offset bytes to be written during the\r
+ write phase of the write-read transaction. This is typically the size of the\r
+ buffer pointed to by the addr_offset parameter.\r
+ \r
+ @param read_buffer:\r
+ This parameter is a pointer to the buffer where the data read from the I2C\r
+ slave will be stored.\r
+ \r
+ @param read_size:\r
+ This parameter specifies the number of bytes to read from the target I2C\r
+ slave device. This size must not exceed the size of the buffer pointed to by\r
+ the read_buffer parameter.\r
+ \r
+ @param options:\r
+ The options parameter is used to indicate if the I2C bus should be released\r
+ on completion of the write-read transaction. Using the I2C_RELEASE_BUS\r
+ constant for the options parameter causes a STOP bit to be generated at the\r
+ end of the write-read transaction causing the bus to be released for other\r
+ I2C devices to use. Using the I2C_HOLD_BUS constant as options parameter\r
+ prevents a STOP bit from being generated at the end of the write-read\r
+ transaction, preventing other I2C devices from initiating a bus transaction.\r
+ \r
+ @return none. \r
+ \r
+ Example:\r
+ @code\r
+ #define COREI2C_BASE_ADDR 0xC0000000u\r
+ #define COREI2C_DUMMY_ADDR 0x10u\r
+ #define TX_LENGTH 16u\r
+ #define RX_LENGTH 8u\r
+\r
+ i2c_instance_t g_i2c_inst;\r
+ uint8_t rx_buffer[RX_LENGTH];\r
+ uint8_t read_length = RX_LENGTH; \r
+ uint8_t tx_buffer[TX_LENGTH];\r
+ uint8_t write_length = TX_LENGTH; \r
+ \r
+ void main( void )\r
+ {\r
+ uint8_t target_slave_addr = 0x12;\r
+ i2c_status_t status;\r
+ // Initialize base CoreI2C instance\r
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, COREI2C_DUMMY_ADDR,\r
+ I2C_PCLK_DIV_256 );\r
+ \r
+ I2C_write_read( &g_i2c_inst, target_slave_addr, tx_buffer, write_length,\r
+ rx_buffer, read_length, I2C_RELEASE_BUS );\r
+ \r
+ status = I2C_wait_complete( &g_i2c_inst, I2C_NO_TIMEOUT );\r
+ }\r
+ @endcode\r
+ */\r
+void I2C_write_read\r
+(\r
+ i2c_instance_t * this_i2c,\r
+ uint8_t serial_addr,\r
+ const uint8_t * addr_offset,\r
+ uint16_t offset_size,\r
+ uint8_t * read_buffer,\r
+ uint16_t read_size,\r
+ uint8_t options\r
+);\r
+ \r
+/*-------------------------------------------------------------------------*//**\r
+ I2C status\r
+ ------------------------------------------------------------------------------\r
+ This function indicates the current state of a CoreI2C channel.\r
+ ------------------------------------------------------------------------------\r
+ @param this_i2c:\r
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure\r
+ holding all data related to a specific CoreI2C channel. For example, if only\r
+ one channel is initialized, this data structure holds the information of \r
+ channel 0 of the instantiated CoreI2C hardware.\r
+ ------------------------------------------------------------------------------\r
+ @return\r
+ The return value indicates the current state of a CoreI2C channel or the\r
+ outcome of the previous transaction if no transaction is in progress. \r
+ Possible return values are:\r
+ I2C_SUCCESS\r
+ The last I2C transaction has completed successfully. \r
+ I2C_IN_PROGRESS\r
+ There is an I2C transaction in progress.\r
+ I2C_FAILED\r
+ The last I2C transaction failed.\r
+ I2C_TIMED_OUT\r
+ The request has failed to complete in the allotted time. \r
+ \r
+ Example:\r
+ @code\r
+ i2c_instance_t g_i2c_inst;\r
+ \r
+ while( I2C_IN_PROGRESS == I2C_get_status( &g_i2c_inst ) )\r
+ {\r
+ // Do something useful while waiting for I2C operation to complete\r
+ our_i2c_busy_task();\r
+ }\r
+ \r
+ if( I2C_SUCCESS != I2C_get_status( &g_i2c_inst ) )\r
+ {\r
+ // Something went wrong... \r
+ our_i2c_error_recovery( &g_i2c_inst );\r
+ }\r
+ @endcode\r
+ */\r
+i2c_status_t I2C_get_status\r
+(\r
+ i2c_instance_t * this_i2c\r
+);\r
+\r
+/*-------------------------------------------------------------------------*//**\r
+ Wait for I2C transaction completion.\r
+ ------------------------------------------------------------------------------\r
+ This function waits for the current I2C transaction to complete. The return\r
+ value indicates whether the last I2C transaction was successful or not.\r
+ ------------------------------------------------------------------------------\r
+ @param this_i2c:\r
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure\r
+ holding all data related to a specific CoreI2C channel. For example, if only\r
+ one channel is initialized, this data structure holds the information of\r
+ channel 0 of the instantiated CoreI2C hardware.\r
+ @param timeout_ms:\r
+ The timeout_ms parameter specified the delay within which the current I2C \r
+ transaction is expected to complete. The time out delay is given in \r
+ milliseconds. I2C_wait_complete() will return I2C_TIMED_OUT if the current\r
+ transaction has not completed after the time out delay has expired. This\r
+ parameter can be set to I2C_NO_TIMEOUT to indicate that I2C_wait_complete()\r
+ must not time out.\r
+ ------------------------------------------------------------------------------\r
+ @return\r
+ The return value indicates the outcome of the last I2C transaction. It can\r
+ be one of the following: \r
+ I2C_SUCCESS\r
+ The last I2C transaction has completed successfully.\r
+ I2C_FAILED\r
+ The last I2C transaction failed.\r
+ I2C_TIMED_OUT\r
+ The last transaction failed to complete within the time out delay given\r
+ as second parameter.\r
+\r
+ Example:\r
+ @code\r
+ #define COREI2C_BASE_ADDR 0xC0000000u\r
+ #define COREI2C_DUMMY_ADDR 0x10u\r
+ #define DATA_LENGTH 16u\r
+\r
+ i2c_instance_t g_i2c_inst;\r
+\r
+ uint8_t rx_buffer[DATA_LENGTH];\r
+ uint8_t read_length = DATA_LENGTH; \r
+\r
+ void main( void )\r
+ {\r
+ uint8_t target_slave_addr = 0x12;\r
+ i2c_status_t status;\r
+ \r
+ // Initialize base CoreI2C instance\r
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, COREI2C_DUMMY_ADDR,\r
+ I2C_PCLK_DIV_256 );\r
+ \r
+ // Read data from Channel 0 of CoreI2C instance.\r
+ I2C_read( &g_i2c_inst, target_slave_addr, rx_buffer, read_length,\r
+ I2C_RELEASE_BUS );\r
+ \r
+ // Wait for completion and record the outcome\r
+ status = I2C_wait_complete( &g_i2c_inst, I2C_NO_TIMEOUT );\r
+ }\r
+ @endcode\r
+ */\r
+i2c_status_t I2C_wait_complete\r
+(\r
+ i2c_instance_t * this_i2c,\r
+ uint32_t timeout_ms\r
+);\r
+\r
+/*-------------------------------------------------------------------------*//**\r
+ Time out delay expiration.\r
+ ------------------------------------------------------------------------------\r
+ This function is used to control the expiration of the time out delay\r
+ specified as a parameter to the I2C_wait_complete() function. It must be\r
+ called from the interrupt service routine of a periodic interrupt source such\r
+ as the Cortex-M3 SysTick timer interrupt. It takes the period of the interrupt\r
+ source as its ms_since_last_tick parameter and uses it as the time base for\r
+ the I2C_wait_complete() function\92s time out delay.\r
+ \r
+ Note: This function does not need to be called if the I2C_wait_complete()\r
+ function is called with a timeout_ms value of I2C_NO_TIMEOUT.\r
+ Note: If this function is not called then the I2C_wait_complete() function\r
+ will behave as if its timeout_ms was specified as I2C_NO_TIMEOUT and it\r
+ will not time out.\r
+ Note: If this function is being called from an interrupt handler (e.g SysTick)\r
+ it is important that the calling interrupt have a lower priority than\r
+ the CoreI2C interrupt(s) to ensure any updates to shared data are\r
+ protected.\r
+ \r
+ ------------------------------------------------------------------------------\r
+ @param this_i2c:\r
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure\r
+ holding all data related to a specific CoreI2C channel. For example, if only\r
+ one channel is initialized, this data structure holds the information of \r
+ channel 0 of the instantiated CoreI2C hardware.\r
+ @param ms_since_last_tick:\r
+ The ms_since_last_tick parameter specifies the number of milliseconds that\r
+ elapsed since the last call to I2C_system_tick(). This parameter would\r
+ typically be a constant specifying the interrupt rate of a timer used to\r
+ generate system ticks.\r
+ ------------------------------------------------------------------------------\r
+ @return\r
+ none.\r
+\r
+ Example:\r
+ The example below shows an example of how the I2C_system_tick() function\r
+ would be called in a Cortex-M3 based system. I2C_system_tick() is called for\r
+ each I2C channel from the Cortex-M3 SysTick timer interrupt service routine.\r
+ The SysTick is configured to generate an interrupt every 10 milliseconds in\r
+ the example below.\r
+ @code\r
+ #define SYSTICK_INTERVAL_MS 10\r
+ \r
+ void SysTick_Handler(void)\r
+ {\r
+ I2C_system_tick(&g_core_i2c0, SYSTICK_INTERVAL_MS);\r
+ I2C_system_tick(&g_core_i2c2, SYSTICK_INTERVAL_MS);\r
+ }\r
+ @endcode\r
+ */\r
+void I2C_system_tick\r
+(\r
+ i2c_instance_t * this_i2c,\r
+ uint32_t ms_since_last_tick\r
+);\r
+\r
+/*******************************************************************************\r
+ *******************************************************************************\r
+ * \r
+ * Slave specific functions\r
+ * \r
+ * The following functions are only used within the implementation of an I2C\r
+ * slave device.\r
+ */\r
+\r
+/*-------------------------------------------------------------------------*//**\r
+ I2C slave transmit buffer configuration.\r
+ ------------------------------------------------------------------------------\r
+ This function specifies the memory buffer holding the data that will be sent\r
+ to the I2C master when this CoreI2C channel is the target of an I2C read or\r
+ write-read transaction.\r
+ ------------------------------------------------------------------------------\r
+ @param this_i2c:\r
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure\r
+ holding all data related to a specific CoreI2C channel. For example, if only\r
+ one channel is initialized, this data structure holds the information of \r
+ channel 0 of the instantiated CoreI2C hardware.\r
+ \r
+ @param tx_buffer:\r
+ This parameter is a pointer to the memory buffer holding the data to be\r
+ returned to the I2C master when this CoreI2C channel is the target of an\r
+ I2C read or write-read transaction.\r
+ \r
+ @param tx_size:\r
+ Size of the transmit buffer pointed to by the tx_buffer parameter.\r
+\r
+ @return none. \r
+ \r
+ Example:\r
+ @code\r
+ #define COREI2C_BASE_ADDR 0xC0000000u\r
+ #define SLAVE_SER_ADDR 0x10u\r
+ #define SLAVE_TX_BUFFER_SIZE 10u\r
+\r
+ i2c_instance_t g_i2c_inst;\r
+\r
+ uint8_t g_slave_tx_buffer[SLAVE_TX_BUFFER_SIZE] = { 1, 2, 3, 4, 5,\r
+ 6, 7, 8, 9, 10 };\r
+\r
+ void main( void )\r
+ {\r
+ // Initialize the CoreI2C driver with its base address, I2C serial\r
+ // address and serial clock divider.\r
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, SLAVE_SER_ADDR,\r
+ I2C_PCLK_DIV_256 );\r
+ \r
+ // Specify the transmit buffer containing the data that will be\r
+ // returned to the master during read and write-read transactions.\r
+ I2C_set_slave_tx_buffer( &g_i2c_inst, g_slave_tx_buffer, \r
+ sizeof(g_slave_tx_buffer) );\r
+ }\r
+ @endcode\r
+ */\r
+void I2C_set_slave_tx_buffer\r
+(\r
+ i2c_instance_t * this_i2c,\r
+ const uint8_t * tx_buffer,\r
+ uint16_t tx_size\r
+);\r
+\r
+/*-------------------------------------------------------------------------*//**\r
+ I2C slave receive buffer configuration.\r
+ ------------------------------------------------------------------------------\r
+ This function specifies the memory buffer that will be used by the CoreI2C\r
+ channel to receive data when it is a slave. This buffer is the memory where\r
+ data will be stored when the CoreI2C channel is the target of an I2C master\r
+ write transaction (i.e. when it is the slave).\r
+ ------------------------------------------------------------------------------\r
+ @param this_i2c:\r
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure\r
+ holding all data related to a specific CoreI2C channel. For example, if only\r
+ one channel is initialized, this data structure holds the information of \r
+ channel 0 of the instantiated CoreI2C hardware.\r
+ \r
+ @param rx_buffer:\r
+ This parameter is a pointer to the memory buffer allocated by the caller\r
+ software to be used as a slave receive buffer.\r
+ \r
+ @param rx_size:\r
+ Size of the slave receive buffer. This is the amount of memory that is\r
+ allocated to the buffer pointed to by rx_buffer.\r
+ Note: This buffer size indirectly specifies the maximum I2C write\r
+ transaction length this CoreI2C channel can be the target of. This\r
+ is because this CoreI2C channel responds to further received\r
+ bytes with a non-acknowledge bit (NACK) as soon as its receive\r
+ buffer is full. This causes the write transaction to fail.\r
+ \r
+ @return none. \r
+ \r
+ Example:\r
+ @code\r
+ #define COREI2C_BASE_ADDR 0xC0000000u\r
+ #define SLAVE_SER_ADDR 0x10u\r
+ #define SLAVE_RX_BUFFER_SIZE 10u\r
+\r
+ i2c_instance_t g_i2c_inst;\r
+\r
+ uint8_t g_slave_rx_buffer[SLAVE_RX_BUFFER_SIZE];\r
+\r
+ void main( void )\r
+ {\r
+ // Initialize the CoreI2C driver with its base address, I2C serial\r
+ // address and serial clock divider.\r
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, SLAVE_SER_ADDR,\r
+ I2C_PCLK_DIV_256 );\r
+ \r
+ // Specify the buffer used to store the data written by the I2C master.\r
+ I2C_set_slave_rx_buffer( &g_i2c_inst, g_slave_rx_buffer, \r
+ sizeof(g_slave_rx_buffer) );\r
+ }\r
+ @endcode\r
+ */\r
+void I2C_set_slave_rx_buffer\r
+(\r
+ i2c_instance_t * this_i2c,\r
+ uint8_t * rx_buffer,\r
+ uint16_t rx_size\r
+);\r
+\r
+/*-------------------------------------------------------------------------*//**\r
+ I2C slave memory offset length configuration.\r
+ ------------------------------------------------------------------------------\r
+ This function is used as part of the configuration of a CoreI2C channel for\r
+ operation as a slave supporting write-read transactions. It specifies the\r
+ number of bytes expected as part of the write phase of a write-read\r
+ transaction. The bytes received during the write phase of a write-read\r
+ transaction will be interpreted as an offset into the slave's transmit buffer.\r
+ This allows random access into the I2C slave transmit buffer from a remote\r
+ I2C master.\r
+ ------------------------------------------------------------------------------\r
+ @param this_i2c:\r
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure\r
+ holding all data related to a specific CoreI2C channel. For example, if only\r
+ one channel is initialized, this data structure holds the information of \r
+ channel 0 of the instantiated CoreI2C hardware.\r
+ \r
+ @param offset_length:\r
+ The offset_length parameter configures the number of bytes to be interpreted\r
+ by the CoreI2C slave as a memory offset value during the write phase of\r
+ write-read transactions. The maximum value for the offset_length parameter\r
+ is two. The value of offset_length has the following effect on the \r
+ interpretation of the received data.\r
+ \r
+ If offset_length is 0, the offset into the transmit buffer is fixed at 0.\r
+ \r
+ If offset_length is 1, a single byte of received data is interpreted as an\r
+ unsigned 8 bit offset value in the range 0 to 255.\r
+ \r
+ If offset_length is 2, 2 bytes of received data are interpreted as an\r
+ unsigned 16 bit offset value in the range 0 to 65535. The first byte\r
+ received in this case provides the high order bits of the offset and\r
+ the second byte provides the low order bits.\r
+ \r
+ If the number of bytes received does not match the non 0 value of\r
+ offset_length the transmit buffer offset is set to 0.\r
+ \r
+ @return none. \r
+ \r
+ Example:\r
+ @code\r
+ #define COREI2C_BASE_ADDR 0xC0000000u\r
+ #define SLAVE_SER_ADDR 0x10u\r
+ #define SLAVE_TX_BUFFER_SIZE 10u\r
+\r
+ i2c_instance_t g_i2c_inst;\r
+\r
+ uint8_t g_slave_tx_buffer[SLAVE_TX_BUFFER_SIZE] = { 1, 2, 3, 4, 5,\r
+ 6, 7, 8, 9, 10 };\r
+\r
+ void main( void )\r
+ {\r
+ // Initialize the CoreI2C driver with its base address, I2C serial\r
+ // address and serial clock divider.\r
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, SLAVE_SER_ADDR,\r
+ I2C_PCLK_DIV_256 );\r
+ I2C_set_slave_tx_buffer( &g_i2c_inst, g_slave_tx_buffer, \r
+ sizeof(g_slave_tx_buffer) );\r
+ I2C_set_slave_mem_offset_length( &g_i2c_inst, 1 );\r
+ }\r
+ @endcode \r
+ */\r
+void I2C_set_slave_mem_offset_length\r
+(\r
+ i2c_instance_t * this_i2c,\r
+ uint8_t offset_length\r
+);\r
+\r
+/*-------------------------------------------------------------------------*//**\r
+ I2C write handler registration. \r
+ ------------------------------------------------------------------------------\r
+ Register the function that is called to process the data written to this\r
+ CoreI2C channel when it is the slave in an I2C write transaction.\r
+ Note: If a write handler is registered, it is called on completion of the\r
+ write phase of a write-read transaction and responsible for processing\r
+ the received data in the slave receive buffer and populating the slave\r
+ transmit buffer with the data that will be transmitted to the I2C master\r
+ as part of the read phase of the write-read transaction. If a write\r
+ handler is not registered, the write data of a write read transaction is\r
+ interpreted as an offset into the slave\92s transmit buffer and handled by\r
+ the driver.\r
+ ------------------------------------------------------------------------------\r
+ @param this_i2c:\r
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure\r
+ holding all data related to a specific CoreI2C channel. For example, if only\r
+ one channel is initialized, this data structure holds the information of \r
+ channel 0 of the instantiated CoreI2C hardware.\r
+ \r
+ @param handler:\r
+ Pointer to the function that will process the I2C write request.\r
+ \r
+ @return none. \r
+ \r
+ Example:\r
+ @code\r
+ #define COREI2C_BASE_ADDR 0xC0000000u\r
+ #define SLAVE_SER_ADDR 0x10u\r
+ #define SLAVE_TX_BUFFER_SIZE 10u\r
+\r
+ i2c_instance_t g_i2c_inst;\r
+\r
+ uint8_t g_slave_tx_buffer[SLAVE_TX_BUFFER_SIZE] = { 1, 2, 3, 4, 5,\r
+ 6, 7, 8, 9, 10 };\r
+\r
+ // local function prototype\r
+ void slave_write_handler\r
+ (\r
+ i2c_instance_t * this_i2c,\r
+ uint8_t * p_rx_data,\r
+ uint16_t rx_size\r
+ );\r
+\r
+ void main( void )\r
+ {\r
+ // Initialize the CoreI2C driver with its base address, I2C serial\r
+ // address and serial clock divider.\r
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, SLAVE_SER_ADDR, \r
+ I2C_PCLK_DIV_256 );\r
+ I2C_set_slave_tx_buffer( &g_i2c_inst, g_slave_tx_buffer, \r
+ sizeof(g_slave_tx_buffer) );\r
+ I2C_set_slave_mem_offset_length( &g_i2c_inst, 1 );\r
+ I2C_register_write_handler( &g_i2c_inst, slave_write_handler );\r
+ }\r
+ @endcode \r
+*/\r
+void I2C_register_write_handler\r
+(\r
+ i2c_instance_t * this_i2c,\r
+ i2c_slave_wr_handler_t handler\r
+);\r
+\r
+/*-------------------------------------------------------------------------*//**\r
+ I2C slave enable.\r
+ ------------------------------------------------------------------------------\r
+ This function enables slave mode operation for a CoreI2C channel. It enables \r
+ the CoreI2C slave to receive data when it is the target of an I2C read, write\r
+ or write-read transaction.\r
+ ------------------------------------------------------------------------------\r
+ @param this_i2c:\r
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure\r
+ holding all data related to a specific CoreI2C channel. For example, if only\r
+ one channel is initialized, this data structure holds the information of \r
+ channel 0 of the instantiated CoreI2C hardware.\r
+\r
+ @return none.\r
+\r
+ Example:\r
+ @code\r
+ // Enable I2C slave\r
+ I2C_enable_slave( &g_i2c_inst );\r
+ @endcode\r
+ */\r
+void I2C_enable_slave\r
+(\r
+ i2c_instance_t * this_i2c\r
+);\r
+\r
+/*-------------------------------------------------------------------------*//**\r
+ I2C slave disable.\r
+ ------------------------------------------------------------------------------\r
+ This function disables slave mode operation for a CoreI2C channel. It stops\r
+ the CoreI2C slave acknowledging I2C read, write or write-read transactions\r
+ targeted at it.\r
+ ------------------------------------------------------------------------------\r
+ @param this_i2c:\r
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure\r
+ holding all data related to a specific CoreI2C channel. For example, if only\r
+ one channel is initialized, this data structure holds the information of \r
+ channel 0 of the instantiated CoreI2C hardware.\r
+\r
+ @return none.\r
+\r
+ Example:\r
+ @code\r
+ // Disable I2C slave\r
+ I2C_disable_slave( &g_i2c_inst );\r
+ @endcode\r
+ */\r
+void I2C_disable_slave\r
+(\r
+ i2c_instance_t * this_i2c\r
+);\r
+/*-------------------------------------------------------------------------*//**\r
+ Set I2C slave second address.\r
+ ------------------------------------------------------------------------------\r
+ The function I2C_set_slave_second_addr() sets the secondary slave address for\r
+ a CoreI2C slave device. This is an additional slave address which might be\r
+ required in certain applications, for example to enable fail-safe operation in\r
+ a system. As the CoreI2C device supports 7-bit addressing, the highest value\r
+ which can be assigned to second slave address is 127 (0x7F).\r
+ Note: This function does not support CoreI2C hardware configured with a fixed \r
+ second slave address. The current implementation of the ADDR1[0] register\r
+ bit makes it difficult for the driver to support both programmable and\r
+ fixed second slave address, so we choose to support programmable only.\r
+ ------------------------------------------------------------------------------\r
+ @param this_i2c:\r
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure\r
+ holding all data related to a specific CoreI2C channel. For example, if only\r
+ one channel is initialized, this data structure holds the information of \r
+ channel 0 of the instantiated CoreI2C hardware.\r
+\r
+ @param second_slave_addr:\r
+ The second_slave_addr parameter is the secondary slave address of the I2C\r
+ device.\r
+\r
+ @return\r
+ none.\r
+\r
+ Example:\r
+ @code\r
+ #define COREI2C_BASE_ADDR 0xC0000000u\r
+ #define SLAVE_SER_ADDR 0x10u\r
+ #define SECOND_SLAVE_ADDR 0x20u\r
+\r
+ i2c_instance_t g_i2c_inst;\r
+ void main( void )\r
+ {\r
+ // Initialize the CoreI2C driver with its base address, primary I2C\r
+ // serial address and serial clock divider.\r
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, SLAVE_SER_ADDR, \r
+ I2C_PCLK_DIV_256 );\r
+ I2C_set_slave_second_addr( &g_i2c_inst, SECOND_SLAVE_ADDR );\r
+ }\r
+ @endcode\r
+ */\r
+void I2C_set_slave_second_addr\r
+(\r
+ i2c_instance_t * this_i2c,\r
+ uint8_t second_slave_addr\r
+);\r
+\r
+/*-------------------------------------------------------------------------*//**\r
+ Disable second slave address.\r
+ ------------------------------------------------------------------------------\r
+ The function I2C_disable_slave_second_addr() disables the secondary slave\r
+ address of the CoreI2C slave device. \r
+ Note: This version of the driver only supports CoreI2C hardware configured\r
+ with a programmable second slave address.\r
+ ------------------------------------------------------------------------------\r
+ @param this_i2c:\r
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure\r
+ holding all data related to a specific CoreI2C channel. For example, if only\r
+ one channel is initialized, this data structure holds the information of \r
+ channel 0 of the instantiated CoreI2C hardware.\r
+\r
+ @return\r
+ none.\r
+\r
+ Example:\r
+ @code\r
+ i2c_instance_t g_i2c_inst;\r
+ I2C_disable_slave_second_addr( &g_i2c_inst);\r
+ @endcode\r
+ */\r
+void I2C_disable_slave_second_addr\r
+(\r
+ i2c_instance_t * this_i2c\r
+);\r
+\r
+/*-------------------------------------------------------------------------*//**\r
+ The I2C_set_gca() function is used to set the general call acknowledgement bit\r
+ of a CoreI2C slave device. This allows all channels of the CoreI2C slave\r
+ device respond to a general call or broadcast message from an I2C master.\r
+ ------------------------------------------------------------------------------\r
+ @param this_i2c:\r
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure\r
+ holding all data related to a specific CoreI2C channel. For example, if only\r
+ one channel is initialized, this data structure holds the information of \r
+ channel 0 of the instantiated CoreI2C hardware.\r
+\r
+ @return\r
+ none.\r
+\r
+ Example:\r
+ @code\r
+ i2c_instance_t g_i2c_inst;\r
+\r
+ // Enable recognition of the General Call Address\r
+ I2C_set_gca( &g_i2c_inst ); \r
+ @endcode\r
+ */\r
+void I2C_set_gca\r
+(\r
+ i2c_instance_t * this_i2c\r
+);\r
+\r
+/*-------------------------------------------------------------------------*//**\r
+ The I2C_clear_gca() function is used to clear the general call acknowledgement\r
+ bit of a CoreI2C slave device. This will stop all channels of the I2C slave\r
+ device responding to any general call or broadcast message from the master.\r
+ ------------------------------------------------------------------------------\r
+ @param this_i2c:\r
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure\r
+ holding all data related to a specific CoreI2C channel. For example, if only\r
+ one channel is initialized, this data structure holds the information of \r
+ channel 0 of the instantiated CoreI2C hardware.\r
+\r
+ @return\r
+ none.\r
+\r
+ Example:\r
+ @code\r
+ i2c_instance_t g_i2c_inst;\r
+\r
+ // Disable recognition of the General Call Address\r
+ I2C_clear_gca( &g_i2c_inst );\r
+ @endcode\r
+ */\r
+\r
+void I2C_clear_gca\r
+(\r
+ i2c_instance_t * this_i2c\r
+);\r
+\r
+/*------------------------------------------------------------------------------\r
+ I2C SMBUS specific APIs\r
+ ----------------------------------------------------------------------------*/\r
+\r
+/*-------------------------------------------------------------------------*//**\r
+ The I2C_smbus_init() function enables SMBus timeouts and status logic for a\r
+ CoreI2C channel.\r
+ Note: This and any of the other SMBus related functionality will only have an\r
+ effect if the CoreI2C was instantiated with the Generate SMBus Logic\r
+ option checked.\r
+ Note: If the CoreI2C was instantiated with the Generate IPMI Logic option\r
+ checked this function will enable the IPMI 3mS SCL low timeout but none\r
+ of the other SMBus functions will have any effect.\r
+ ------------------------------------------------------------------------------\r
+ @param this_i2c:\r
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure\r
+ holding all data related to a specific CoreI2C channel. For example, if only\r
+ one channel is initialized, this data structure holds the information of \r
+ channel 0 of the instantiated CoreI2C hardware.\r
+\r
+ @return\r
+ none.\r
+\r
+ Example:\r
+ @code\r
+ #define COREI2C_BASE_ADDR 0xC0000000u\r
+ #define SLAVE_SER_ADDR 0x10u\r
+\r
+ i2c_instance_t g_i2c_inst;\r
+\r
+ void system_init( void )\r
+ {\r
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, SLAVE_SER_ADDR,\r
+ I2C_PCLK_DIV_256 );\r
+ \r
+ // Initialize SMBus feature\r
+ I2C_smbus_init( &g_i2c_inst);\r
+ }\r
+ @endcode \r
+ */\r
+void I2C_smbus_init\r
+(\r
+ i2c_instance_t * this_i2c\r
+);\r
+\r
+/*-------------------------------------------------------------------------*//**\r
+ The I2C_enable_smbus_irq() function is used to enable the CoreI2C channel\92s \r
+ SMBSUS and SMBALERT SMBus interrupts.\r
+ ------------------------------------------------------------------------------\r
+ @param this_i2c:\r
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure\r
+ holding all data related to a specific CoreI2C channel. For example, if only\r
+ one channel is initialized, this data structure holds the information of \r
+ channel 0 of the instantiated CoreI2C hardware.\r
+\r
+ @param irq_type\r
+ The irq_type specify the SMBUS interrupt(s) which will be enabled.\r
+ The two possible interrupts are:\r
+ I2C_SMBALERT_IRQ\r
+ I2C_SMBSUS_IRQ\r
+ To enable both ints in one call, use I2C_SMBALERT_IRQ | I2C_SMBSUS_IRQ.\r
+ \r
+ @return\r
+ none\r
+ \r
+ Example:\r
+ @code\r
+ #define COREI2C_BASE_ADDR 0xC0000000u\r
+ #define SLAVE_SER_ADDR 0x10u\r
+\r
+ i2c_instance_t g_i2c_inst;\r
+\r
+ void main( void )\r
+ {\r
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, SLAVE_SER_ADDR,\r
+ I2C_PCLK_DIV_256 );\r
+ \r
+ // Initialize SMBus feature\r
+ I2C_smbus_init( &g_i2c_inst );\r
+ \r
+ // Enable both I2C_SMBALERT_IRQ & I2C_SMBSUS_IRQ interrupts\r
+ I2C_enable_smbus_irq( &g_i2c_inst,\r
+ (uint8_t)(I2C_SMBALERT_IRQ | I2C_SMBSUS_IRQ) );\r
+ }\r
+ @endcode\r
+ */\r
+void I2C_enable_smbus_irq\r
+(\r
+ i2c_instance_t * this_i2c,\r
+ uint8_t irq_type\r
+);\r
+\r
+/*-------------------------------------------------------------------------*//**\r
+ The I2C_disable_smbus_irq() function is used to disable the CoreI2C channel\92s\r
+ SMBSUS and SMBALERT SMBus interrupts.\r
+ ------------------------------------------------------------------------------\r
+ @param this_i2c:\r
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure\r
+ holding all data related to a specific CoreI2C channel. For example, if only\r
+ one channel is initialized, this data structure holds the information of \r
+ channel 0 of the instantiated CoreI2C hardware.\r
+\r
+ @param irq_type\r
+ The irq_type specifies the SMBUS interrupt(s) which will be disabled.\r
+ The two possible interrupts are:\r
+ I2C_SMBALERT_IRQ\r
+ I2C_SMBSUS_IRQ\r
+ To disable both ints in one call, use I2C_SMBALERT_IRQ | I2C_SMBSUS_IRQ.\r
+\r
+ @return\r
+ none.\r
+ \r
+ Example:\r
+ @code\r
+ #define COREI2C_BASE_ADDR 0xC0000000u\r
+ #define SLAVE_SER_ADDR 0x10u\r
+\r
+ i2c_instance_t g_i2c_inst;\r
+\r
+ void main( void )\r
+ {\r
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, SLAVE_SER_ADDR,\r
+ I2C_PCLK_DIV_256 );\r
+ \r
+ // Initialize SMBus feature\r
+ I2C_smbus_init( &g_i2c_inst );\r
+ \r
+ // Enable both SMBALERT & SMBSUS interrupts\r
+ I2C_enable_smbus_irq( &g_i2c_inst,\r
+ (uint8_t)(I2C_SMBALERT_IRQ | I2C_SMBSUS_IRQ));\r
+ \r
+ ... \r
+\r
+ // Disable the SMBALERT interrupt\r
+ I2C_disable_smbus_irq( &g_i2c_inst, I2C_SMBALERT_IRQ );\r
+ }\r
+ @endcode\r
+ */\r
+void I2C_disable_smbus_irq\r
+(\r
+ i2c_instance_t * this_i2c,\r
+ uint8_t irq_type\r
+);\r
+\r
+/*-------------------------------------------------------------------------*//**\r
+ The function I2C_suspend_smbus_slave() forces any SMBUS slave devices\r
+ connected to a CoreI2C channel into power down or suspend mode by asserting\r
+ the channel's SMBSUS signal. The CoreI2C channel is the SMBus master in this\r
+ case.\r
+ ------------------------------------------------------------------------------\r
+ @param this_i2c:\r
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure\r
+ holding all data related to a specific CoreI2C channel. For example, if only\r
+ one channel is initialized, this data structure holds the information of \r
+ channel 0 of the instantiated CoreI2C hardware.\r
+\r
+ @return\r
+ none.\r
+ \r
+ Example:\r
+ @code\r
+ #define COREI2C_BASE_ADDR 0xC0000000u\r
+ #define SLAVE_SER_ADDR 0x10u\r
+\r
+ i2c_instance_t g_i2c_inst;\r
+ \r
+ void main( void )\r
+ {\r
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, SLAVE_SER_ADDR, \r
+ I2C_PCLK_DIV_256 );\r
+\r
+ // Initialize SMBus feature\r
+ I2C_smbus_init( &g_i2c_inst );\r
+\r
+ // suspend SMBus slaves\r
+ I2C_suspend_smbus_slave( &g_i2c_inst );\r
+\r
+ ...\r
+\r
+ // Re-enable SMBus slaves\r
+ I2C_resume_smbus_slave( &g_i2c_inst );\r
+ }\r
+ @endcode\r
+ */\r
+void I2C_suspend_smbus_slave\r
+(\r
+ i2c_instance_t * this_i2c\r
+);\r
+\r
+/*-------------------------------------------------------------------------*//**\r
+ The function I2C_resume_smbus_slave() de-asserts the CoreI2C channel's SMBSUS\r
+ signal to take any connected slave devices out of suspend mode. The CoreI2C\r
+ channel is the SMBus master in this case.\r
+ ------------------------------------------------------------------------------\r
+ @param this_i2c:\r
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure\r
+ holding all data related to a specific CoreI2C channel. For example, if only\r
+ one channel is initialized, this data structure holds the information of \r
+ channel 0 of the instantiated CoreI2C hardware.\r
+\r
+ @return\r
+ none.\r
+ \r
+ Example:\r
+ @code\r
+ #define COREI2C_BASE_ADDR 0xC0000000u\r
+ #define SLAVE_SER_ADDR 0x10u\r
+\r
+ i2c_instance_t g_i2c_inst;\r
+ \r
+ void main( void )\r
+ {\r
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, SLAVE_SER_ADDR, \r
+ I2C_PCLK_DIV_256 );\r
+\r
+ // Initialize SMBus feature\r
+ I2C_smbus_init( &g_i2c_inst );\r
+\r
+ // suspend SMBus slaves\r
+ I2C_suspend_smbus_slave( &g_i2c_inst );\r
+\r
+ ...\r
+\r
+ // Re-enable SMBus slaves\r
+ I2C_resume_smbus_slave( &g_i2c_inst );\r
+ }\r
+ @endcode\r
+ */\r
+void I2C_resume_smbus_slave\r
+(\r
+ i2c_instance_t * this_i2c\r
+);\r
+\r
+/*-------------------------------------------------------------------------*//**\r
+ The I2C_reset_smbus() function resets the CoreI2C channel's SMBus connection\r
+ by forcing SCLK low for 35mS. The reset is automatically cleared after 35ms\r
+ have elapsed. The CoreI2C channel is the SMBus master in this case.\r
+ ------------------------------------------------------------------------------\r
+ @param this_i2c:\r
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure\r
+ holding all data related to a specific CoreI2C channel. For example, if only\r
+ one channel is initialized, this data structure holds the information of \r
+ channel 0 of the instantiated CoreI2C hardware.\r
+\r
+ @return\r
+ none.\r
+\r
+ Example:\r
+ @code\r
+ #define COREI2C_BASE_ADDR 0xC0000000u\r
+ #define SLAVE_SER_ADDR 0x10u\r
+\r
+ i2c_instance_t g_i2c_inst;\r
+ \r
+ void main( void )\r
+ {\r
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, SLAVE_SER_ADDR, \r
+ I2C_PCLK_DIV_256 );\r
+\r
+ // Initialize SMBus feature\r
+ I2C_smbus_init( &g_i2c_inst );\r
+\r
+ // Make sure the SMBus channel is in a known state by resetting it\r
+ I2C_reset_smbus( &g_i2c_inst ); \r
+ }\r
+ @endcode\r
+ */\r
+void I2C_reset_smbus\r
+(\r
+ i2c_instance_t * this_i2c\r
+);\r
+\r
+/*-------------------------------------------------------------------------*//**\r
+ The I2C_set_smbus_alert() function is used to force master communication with\r
+ an I2C slave device by asserting the CoreI2C channel\92s SMBALERT signal. The\r
+ CoreI2C channel is the SMBus slave in this case.\r
+ ------------------------------------------------------------------------------\r
+ @param this_i2c:\r
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure\r
+ holding all data related to a specific CoreI2C channel. For example, if only\r
+ one channel is initialized, this data structure holds the information of \r
+ channel 0 of the instantiated CoreI2C hardware.\r
+\r
+ @return\r
+ none.\r
+\r
+ Example:\r
+ @code\r
+ #define COREI2C_BASE_ADDR 0xC0000000u\r
+ #define SLAVE_SER_ADDR 0x10u\r
+\r
+ i2c_instance_t g_i2c_inst;\r
+ \r
+ void main( void )\r
+ {\r
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, SLAVE_SER_ADDR, \r
+ I2C_PCLK_DIV_256 );\r
+\r
+ // Initialize SMBus feature\r
+ I2C_smbus_init( &g_i2c_inst );\r
+\r
+ // Get the SMBus masters attention\r
+ I2C_set_smbus_alert( &g_i2c_inst );\r
+\r
+ ...\r
+\r
+ // Once we are happy, drop the alert\r
+ I2C_clear_smbus_alert( &g_i2c_inst );\r
+ }\r
+ @endcode\r
+ */\r
+void I2C_set_smbus_alert\r
+(\r
+ i2c_instance_t * this_i2c\r
+);\r
+\r
+/*-------------------------------------------------------------------------*//**\r
+ The I2C_clear_smbus_alert() function is used de-assert the CoreI2C channel\92s \r
+ SMBALERT signal once a slave device has had a response from the master. The\r
+ CoreI2C channel is the SMBus slave in this case.\r
+ ------------------------------------------------------------------------------\r
+ @param this_i2c:\r
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure\r
+ holding all data related to a specific CoreI2C channel. For example, if only\r
+ one channel is initialized, this data structure holds the information of \r
+ channel 0 of the instantiated CoreI2C hardware.\r
+\r
+ @return\r
+ none.\r
+ \r
+ Example:\r
+ @code\r
+ #define COREI2C_BASE_ADDR 0xC0000000u\r
+ #define SLAVE_SER_ADDR 0x10u\r
+\r
+ i2c_instance_t g_i2c_inst;\r
+ \r
+ void main( void )\r
+ {\r
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, SLAVE_SER_ADDR, \r
+ I2C_PCLK_DIV_256 );\r
+\r
+ // Initialize SMBus feature\r
+ I2C_smbus_init( &g_i2c_inst );\r
+\r
+ // Get the SMBus masters attention\r
+ I2C_set_smbus_alert( &g_i2c_inst );\r
+\r
+ ...\r
+\r
+ // Once we are happy, drop the alert\r
+ I2C_clear_smbus_alert( &g_i2c_inst );\r
+ }\r
+ @endcode\r
+ */\r
+void I2C_clear_smbus_alert\r
+(\r
+ i2c_instance_t * this_i2c\r
+);\r
+\r
+/*-------------------------------------------------------------------------*//**\r
+ The I2C_get_irq_status function returns information on which interrupts are\r
+ currently pending in a CoreI2C channel.\r
+ The interrupts supported by CoreI2C are:\r
+ * SMBUSALERT\r
+ * SMBSUS\r
+ * INTR\r
+ The macros I2C_NO_IRQ, I2C_SMBALERT_IRQ, I2C_SMBSUS_IRQ and I2C_INTR_IRQ are\r
+ provided for use with this function.\r
+ ------------------------------------------------------------------------------\r
+ @param this_i2c:\r
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure\r
+ holding all data related to a specific CoreI2C channel. For example, if only\r
+ one channel is initialized, this data structure holds the information of \r
+ channel 0 of the instantiated CoreI2C hardware.\r
+\r
+ @return\r
+ This function returns the status of the CoreI2C channel\92s interrupts as a \r
+ single byte bitmap where a bit is set to indicate a pending interrupt.\r
+ The following are the bit positions associated with each interrupt type:\r
+ Bit 0 - SMBUS_ALERT_IRQ\r
+ Bit 1 - SMBSUS_IRQ\r
+ Bit 2 - INTR_IRQ\r
+ It returns 0, if there are no pending interrupts.\r
+\r
+ Example\r
+ @code\r
+ #define COREI2C_BASE_ADDR 0xC0000000u\r
+ #define SLAVE_SER_ADDR 0x10u\r
+\r
+ i2c_instance_t g_i2c_inst;\r
+ \r
+ void main( void )\r
+ {\r
+ uint8_t irq_to_enable = I2C_SMBALERT_IRQ | I2C_SMBSUS_IRQ;\r
+ uint8_t pending_irq = 0u;\r
+ \r
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, SLAVE_SER_ADDR,\r
+ I2C_PCLK_DIV_256 );\r
+\r
+ // Initialize SMBus feature\r
+ I2C_smbus_init( &g_i2c_inst );\r
+\r
+ // Enable both I2C_SMBALERT_IRQ & I2C_SMBSUS_IRQ irq\r
+ I2C_enable_smbus_irq( &g_i2c_inst, irq_to_enable );\r
+\r
+ // Get I2C IRQ type\r
+ pending_irq = I2C_get_irq_status( &g_i2c_inst );\r
+\r
+ // Let's assume, in system, INTR and SMBALERT IRQ is pending.\r
+ // So pending_irq will return status of both the IRQs\r
+\r
+ if( pending_irq & I2C_SMBALERT_IRQ )\r
+ {\r
+ // if true, it means SMBALERT_IRQ is there in pending IRQ list\r
+ }\r
+ if( pending_irq & I2C_INTR_IRQ )\r
+ {\r
+ // if true, it means I2C_INTR_IRQ is there in pending IRQ list\r
+ }\r
+ }\r
+ @endcode\r
+ */\r
+uint8_t I2C_get_irq_status\r
+(\r
+ i2c_instance_t * this_i2c\r
+);\r
+\r
+/*-------------------------------------------------------------------------*//**\r
+ The I2C_set_user_data() function is used to allow the association of a block\r
+ of application specific data with a CoreI2C channel. The composition of the \r
+ data block is an application matter and the driver simply provides the means\r
+ for the application to set and retrieve the pointer. This may for example be\r
+ used to provide additional channel specific information to the slave write \r
+ handler.\r
+ ------------------------------------------------------------------------------\r
+ @param this_i2c:\r
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure\r
+ holding all data related to a specific CoreI2C channel. For example, if only\r
+ one channel is initialized, this data structure holds the information of \r
+ channel 0 of the instantiated CoreI2C hardware.\r
+\r
+ @param p_user_data:\r
+ The p_user_data parameter is a pointer to the user specific data block for\r
+ this channel. It is defined as void * as the driver does not know the actual\r
+ type of data being pointed to and simply stores the pointer for later\r
+ retrieval by the application.\r
+\r
+ @return\r
+ none.\r
+ \r
+ Example\r
+ @code\r
+ #define COREI2C_BASE_ADDR 0xC0000000u\r
+ #define SLAVE_SER_ADDR 0x10u\r
+\r
+ i2c_instance_t g_i2c_inst;\r
+ app_data_t channel_xdata;\r
+ \r
+ void main( void )\r
+ {\r
+ app_data_t *p_xdata;\r
+\r
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, SLAVE_SER_ADDR, \r
+ I2C_PCLK_DIV_256 );\r
+\r
+ // Store location of user data in instance structure\r
+ I2C_set_user_data( &g_i2c_inst, (void *)&channel_xdata );\r
+\r
+ ...\r
+\r
+ // Retrieve location of user data and do some work on it\r
+ p_xdata = (app_data_t *)I2C_get_user_data( &g_i2c_inst );\r
+ if( NULL != p_xdata )\r
+ {\r
+ p_xdata->foo = 123;\r
+ }\r
+ }\r
+ @endcode\r
+ */\r
+void I2C_set_user_data\r
+(\r
+ i2c_instance_t * this_i2c,\r
+ void * p_user_data\r
+);\r
+\r
+/*-------------------------------------------------------------------------*//**\r
+ The I2C_get_user_data() function is used to allow the retrieval of the address\r
+ of a block of application specific data associated with a CoreI2C channel.\r
+ The composition of the data block is an application matter and the driver \r
+ simply provides the means for the application to set and retrieve the pointer.\r
+ This may for example be used to provide additional channel specific\r
+ information to the slave write handler.\r
+ ------------------------------------------------------------------------------\r
+ @param this_i2c:\r
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure\r
+ holding all data related to a specific CoreI2C channel. For example, if only\r
+ one channel is initialized, this data structure holds the information of \r
+ channel 0 of the instantiated CoreI2C hardware.\r
+\r
+ @return\r
+ This function returns a pointer to the user specific data block for this \r
+ channel. It is defined as void * as the driver does not know the actual type\r
+ of data being pointed. If no user data has been registered for this channel\r
+ a NULL pointer is returned.\r
+ \r
+ Example\r
+ @code\r
+ #define COREI2C_BASE_ADDR 0xC0000000u\r
+ #define SLAVE_SER_ADDR 0x10u\r
+\r
+ i2c_instance_t g_i2c_inst;\r
+ app_data_t channel_xdata;\r
+ \r
+ void main( void )\r
+ {\r
+ app_data_t *p_xdata;\r
+\r
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, SLAVE_SER_ADDR,\r
+ I2C_PCLK_DIV_256 );\r
+\r
+ // Store location of user data in instance structure\r
+ I2C_set_user_data( &g_i2c_inst, (void *)&channel_xdata );\r
+\r
+ ...\r
+ \r
+ // Retrieve location of user data and do some work on it\r
+ p_xdata = (app_data_t *)I2C_get_user_data( &g_i2c_inst );\r
+ if( NULL != p_xdata )\r
+ {\r
+ p_xdata->foo = 123;\r
+ }\r
+ }\r
+ @endcode\r
+ */\r
+void * I2C_get_user_data\r
+(\r
+ i2c_instance_t * this_i2c\r
+);\r
+\r
+#ifdef __cplusplus\r
+}\r
+#endif\r
+\r
+#endif\r
--- /dev/null
+/*******************************************************************************\r
+ * (c) Copyright 2009-2015 Microsemi SoC Products Group. All rights reserved.\r
+ * \r
+ * SVN $Revision: 7984 $\r
+ * SVN $Date: 2015-10-12 12:07:40 +0530 (Mon, 12 Oct 2015) $\r
+ */\r
+\r
+#ifndef __CORE_SMBUS_REGISTERS\r
+#define __CORE_SMBUS_REGISTERS 1\r
+\r
+/*------------------------------------------------------------------------------\r
+ * CONTROL register details\r
+ */\r
+#define CONTROL_REG_OFFSET 0x00u\r
+\r
+/*\r
+ * CR0 bits.\r
+ */\r
+#define CR0_OFFSET 0x00u\r
+#define CR0_MASK 0x01u\r
+#define CR0_SHIFT 0u\r
+\r
+/*\r
+ * CR1 bits.\r
+ */\r
+#define CR1_OFFSET 0x00u\r
+#define CR1_MASK 0x02u\r
+#define CR1_SHIFT 1u\r
+\r
+/*\r
+ * AA bits.\r
+ */\r
+#define AA_OFFSET 0x00u\r
+#define AA_MASK 0x04u\r
+#define AA_SHIFT 2u\r
+\r
+/*\r
+ * SI bits.\r
+ */\r
+#define SI_OFFSET 0x00u\r
+#define SI_MASK 0x08u\r
+#define SI_SHIFT 3u\r
+\r
+/*\r
+ * STO bits.\r
+ */\r
+#define STO_OFFSET 0x00u\r
+#define STO_MASK 0x10u\r
+#define STO_SHIFT 4u\r
+\r
+/*\r
+ * STA bits.\r
+ */\r
+#define STA_OFFSET 0x00u\r
+#define STA_MASK 0x20u\r
+#define STA_SHIFT 5u\r
+\r
+/*\r
+ * ENS1 bits.\r
+ */\r
+#define ENS1_OFFSET 0x00u\r
+#define ENS1_MASK 0x40u\r
+#define ENS1_SHIFT 6u\r
+\r
+/*\r
+ * CR2 bits.\r
+ */\r
+#define CR2_OFFSET 0x00u\r
+#define CR2_MASK 0x80u\r
+#define CR2_SHIFT 7u\r
+\r
+/*------------------------------------------------------------------------------\r
+ * STATUS register details\r
+ */\r
+#define STATUS_REG_OFFSET 0x04u\r
+\r
+/*------------------------------------------------------------------------------\r
+ * DATA register details\r
+ */\r
+#define DATA_REG_OFFSET 0x08u\r
+\r
+/*\r
+ * TARGET_ADDR bits.\r
+ */\r
+#define TARGET_ADDR_OFFSET 0x08u\r
+#define TARGET_ADDR_MASK 0xFEu\r
+#define TARGET_ADDR_SHIFT 1u\r
+ \r
+/*\r
+ * DIR bit.\r
+ */\r
+#define DIR_OFFSET 0x08u\r
+#define DIR_MASK 0x01u\r
+#define DIR_SHIFT 0u\r
+\r
+\r
+/*------------------------------------------------------------------------------\r
+ * ADDRESS register details\r
+ */\r
+#define ADDRESS_REG_OFFSET 0x0Cu\r
+\r
+/*\r
+ * GC bits.\r
+ */\r
+#define GC_OFFSET 0x0Cu\r
+#define GC_MASK 0x01u\r
+#define GC_SHIFT 0u\r
+\r
+/*\r
+ * ADR bits.\r
+ */\r
+#define OWN_SLAVE_ADDR_OFFSET 0x0Cu\r
+#define OWN_SLAVE_ADDR_MASK 0xFEu\r
+#define OWN_SLAVE_ADDR_SHIFT 1u\r
+\r
+/*------------------------------------------------------------------------------\r
+ * SMBUS register details\r
+ */\r
+#define SMBUS_REG_OFFSET 0x10u\r
+\r
+/*\r
+ * SMBALERT_IE bits.\r
+ */\r
+#define SMBALERT_IE_OFFSET 0x10u\r
+#define SMBALERT_IE_MASK 0x01u\r
+#define SMBALERT_IE_SHIFT 0u\r
+\r
+/*\r
+ * SMBSUS_IE bits.\r
+ */\r
+#define SMBSUS_IE_OFFSET 0x10u\r
+#define SMBSUS_IE_MASK 0x02u\r
+#define SMBSUS_IE_SHIFT 1u\r
+\r
+/*\r
+ * SMB_IPMI_EN bits.\r
+ */\r
+#define SMB_IPMI_EN_OFFSET 0x10u\r
+#define SMB_IPMI_EN_MASK 0x04u\r
+#define SMB_IPMI_EN_SHIFT 2u\r
+\r
+/*\r
+ * SMBALERT_NI_STATUS bits.\r
+ */\r
+#define SMBALERT_NI_STATUS_OFFSET 0x10u\r
+#define SMBALERT_NI_STATUS_MASK 0x08u\r
+#define SMBALERT_NI_STATUS_SHIFT 3u\r
+\r
+/*\r
+ * SMBALERT_NO_CONTROL bits.\r
+ */\r
+#define SMBALERT_NO_CONTROL_OFFSET 0x10u\r
+#define SMBALERT_NO_CONTROL_MASK 0x10u\r
+#define SMBALERT_NO_CONTROL_SHIFT 4u\r
+\r
+/*\r
+ * SMBSUS_NI_STATUS bits.\r
+ */\r
+#define SMBSUS_NI_STATUS_OFFSET 0x10u\r
+#define SMBSUS_NI_STATUS_MASK 0x20u\r
+#define SMBSUS_NI_STATUS_SHIFT 5u\r
+\r
+/*\r
+ * SMBSUS_NO_CONTROL bits.\r
+ */\r
+#define SMBSUS_NO_CONTROL_OFFSET 0x10u\r
+#define SMBSUS_NO_CONTROL_MASK 0x40u\r
+#define SMBSUS_NO_CONTROL_SHIFT 6u\r
+\r
+/*\r
+ * SMBUS_MST_RESET bits.\r
+ */\r
+#define SMBUS_MST_RESET_OFFSET 0x10u\r
+#define SMBUS_MST_RESET_MASK 0x80u\r
+#define SMBUS_MST_RESET_SHIFT 7u\r
+\r
+/*------------------------------------------------------------------------------\r
+ * SLAVE ADDRESS 1 register details\r
+ */\r
+\r
+#define ADDRESS1_REG_OFFSET 0x1Cu\r
+\r
+/*\r
+ * SLAVE1_EN bit of Slave Address 1 .\r
+ */\r
+#define SLAVE1_EN_OFFSET 0x1Cu\r
+#define SLAVE1_EN_MASK 0x01u\r
+#define SLAVE1_EN_SHIFT 0u\r
+\r
+#endif /* __CORE_SMBUS_REGISTERS */\r
--- /dev/null
+/*******************************************************************************\r
+ * (c) Copyright 2009-2015 Microsemi SoC Products Group. All rights reserved.\r
+ * \r
+ * CoreI2C driver interrupt control.\r
+ * \r
+ * SVN $Revision: 7984 $\r
+ * SVN $Date: 2015-10-12 12:07:40 +0530 (Mon, 12 Oct 2015) $\r
+ */\r
+#include "hal.h"\r
+#include "hal_assert.h"\r
+#include "core_i2c.h"\r
+#include "riscv_hal.h"\r
+\r
+\r
+#define I2C_IRQn External_29_IRQn\r
+\r
+/*------------------------------------------------------------------------------\r
+ * This function must be modified to enable interrupts generated from the\r
+ * CoreI2C instance identified as parameter.\r
+ */\r
+void I2C_enable_irq( i2c_instance_t * this_i2c )\r
+{\r
+ PLIC_EnableIRQ(I2C_IRQn);\r
+// HAL_ASSERT(0)\r
+}\r
+\r
+/*------------------------------------------------------------------------------\r
+ * This function must be modified to disable interrupts generated from the\r
+ * CoreI2C instance identified as parameter.\r
+ */\r
+void I2C_disable_irq( i2c_instance_t * this_i2c )\r
+{\r
+ PLIC_DisableIRQ(I2C_IRQn);\r
+// HAL_ASSERT(0)\r
+}\r
--- /dev/null
+/*******************************************************************************\r
+ * (c) Copyright 2007-2015 Microsemi SoC Products Group. All rights reserved.\r
+ * \r
+ * CoreTimer driver implementation.\r
+ * \r
+ * SVN $Revision: 7967 $\r
+ * SVN $Date: 2015-10-09 18:48:26 +0530 (Fri, 09 Oct 2015) $\r
+ */\r
+\r
+#include "core_timer.h"\r
+#include "coretimer_regs.h"\r
+#include "hal.h"\r
+#include "hal_assert.h"\r
+\r
+#ifndef NDEBUG\r
+static timer_instance_t* NULL_timer_instance;\r
+#endif\r
+\r
+/***************************************************************************//**\r
+ * TMR_init()\r
+ * See "core_timer.h" for details of how to use this function.\r
+ */\r
+void \r
+TMR_init\r
+(\r
+ timer_instance_t * this_timer,\r
+ addr_t address,\r
+ uint8_t mode,\r
+ uint32_t prescale,\r
+ uint32_t load_value\r
+)\r
+{\r
+ HAL_ASSERT( this_timer != NULL_timer_instance )\r
+ HAL_ASSERT( prescale <= PRESCALER_DIV_1024 )\r
+ HAL_ASSERT( load_value != 0 )\r
+ \r
+ this_timer->base_address = address;\r
+\r
+ /* Disable interrupts. */\r
+ HAL_set_32bit_reg_field( address, InterruptEnable,0 );\r
+\r
+ /* Disable timer. */\r
+ HAL_set_32bit_reg_field( address, TimerEnable, 0 );\r
+\r
+ /* Clear pending interrupt. */\r
+ HAL_set_32bit_reg( address, TimerIntClr, 1 );\r
+\r
+ /* Configure prescaler and load value. */ \r
+ HAL_set_32bit_reg( address, TimerPrescale, prescale );\r
+ HAL_set_32bit_reg( address, TimerLoad, load_value );\r
+\r
+ /* Set the interrupt mode. */\r
+ if ( mode == TMR_CONTINUOUS_MODE )\r
+ {\r
+ HAL_set_32bit_reg_field( address, TimerMode, 0 );\r
+ }\r
+ else\r
+ {\r
+ /* TMR_ONE_SHOT_MODE */\r
+ HAL_set_32bit_reg_field( address, TimerMode, 1 );\r
+ }\r
+}\r
+\r
+/***************************************************************************//**\r
+ * TMR_start()\r
+ * See "core_timer.h" for details of how to use this function.\r
+ */\r
+void\r
+TMR_start\r
+(\r
+ timer_instance_t * this_timer\r
+)\r
+{\r
+ HAL_ASSERT( this_timer != NULL_timer_instance )\r
+ \r
+ HAL_set_32bit_reg_field( this_timer->base_address, TimerEnable, 1 );\r
+}\r
+\r
+/***************************************************************************//**\r
+ * TMR_stop()\r
+ * See "core_timer.h" for details of how to use this function.\r
+ */\r
+void\r
+TMR_stop\r
+(\r
+ timer_instance_t * this_timer\r
+)\r
+{\r
+ HAL_ASSERT( this_timer != NULL_timer_instance )\r
+ \r
+ HAL_set_32bit_reg_field( this_timer->base_address, TimerEnable, 0 );\r
+}\r
+\r
+\r
+/***************************************************************************//**\r
+ * TMR_enable_int()\r
+ * See "core_timer.h" for details of how to use this function.\r
+ */\r
+void\r
+TMR_enable_int\r
+(\r
+ timer_instance_t * this_timer\r
+)\r
+{\r
+ HAL_ASSERT( this_timer != NULL_timer_instance )\r
+ \r
+ HAL_set_32bit_reg_field( this_timer->base_address, InterruptEnable, 1 );\r
+}\r
+\r
+/***************************************************************************//**\r
+ * TMR_clear_int()\r
+ * See "core_timer.h" for details of how to use this function.\r
+ */\r
+void\r
+TMR_clear_int\r
+(\r
+ timer_instance_t * this_timer\r
+)\r
+{\r
+ HAL_ASSERT( this_timer != NULL_timer_instance )\r
+ \r
+ HAL_set_32bit_reg( this_timer->base_address, TimerIntClr, 0x01 );\r
+}\r
+\r
+/***************************************************************************//**\r
+ * TMR_current_value()\r
+ * See "core_timer.h" for details of how to use this function.\r
+ */\r
+uint32_t\r
+TMR_current_value\r
+(\r
+ timer_instance_t * this_timer\r
+)\r
+{\r
+ uint32_t value = 0;\r
+ HAL_ASSERT( this_timer != NULL_timer_instance )\r
+ \r
+ value = HAL_get_32bit_reg( this_timer->base_address, TimerValue );\r
+ \r
+ return value;\r
+}\r
+\r
+/***************************************************************************//**\r
+ * TMR_reload()\r
+ * See "core_timer.h" for details of how to use this function.\r
+ */\r
+void TMR_reload\r
+(\r
+ timer_instance_t * this_timer,\r
+ uint32_t load_value\r
+)\r
+{\r
+ HAL_ASSERT( this_timer != NULL_timer_instance )\r
+ HAL_ASSERT( load_value != 0 )\r
+ \r
+ HAL_set_32bit_reg(this_timer->base_address, TimerLoad, load_value );\r
+}\r
+\r
--- /dev/null
+/*******************************************************************************\r
+ * (c) Copyright 2007-2015 Microsemi SoC Products Group. All rights reserved.\r
+ * \r
+ * CoreTimer public API.\r
+ * \r
+ * SVN $Revision: 7967 $\r
+ * SVN $Date: 2015-10-09 18:48:26 +0530 (Fri, 09 Oct 2015) $\r
+ */\r
+#ifndef CORE_TIMER_H_\r
+#define CORE_TIMER_H_\r
+\r
+#include "cpu_types.h"\r
+\r
+/***************************************************************************//**\r
+ * The following definitions are used to select the CoreTimer driver operating\r
+ * mode. They allow selecting continuous or one-shot mode.\r
+ * 1. Continuous Mode\r
+ * In continuous mode the timer's counter is decremented from the load value \r
+ * until it reaches zero. The timer counter is automatically reloaded, with the\r
+ * load value, upon reaching zero. An interrupt is generated every time the\r
+ * counter reaches zero if interrupt is enabled.\r
+ * This mode is typically used to generate an interrupt at constant time\r
+ * intervals.\r
+ * 2. One-shot mode: \r
+ * In one-shot mode, the counter decrements from the load value and until it\r
+ * reaches zero. An interrupt can be generated, if enabled, when the counter\r
+ * reaches zero. The timer's counter must be reloaded to begin counting down\r
+ * again.\r
+ */\r
+#define TMR_CONTINUOUS_MODE 0\r
+#define TMR_ONE_SHOT_MODE 1\r
+\r
+/***************************************************************************//**\r
+ * The following definitions are used to configure the CoreTimer prescaler.\r
+ * The prescaler is used to divide down the clock used to decrement the\r
+ * CoreTimer counter. It can be configure to divide the clock by 2, 4, 8,\r
+ * 16, 32, 64, 128, 256, 512, or 1024.\r
+ */\r
+#define PRESCALER_DIV_2 0\r
+#define PRESCALER_DIV_4 1\r
+#define PRESCALER_DIV_8 2\r
+#define PRESCALER_DIV_16 3\r
+#define PRESCALER_DIV_32 4\r
+#define PRESCALER_DIV_64 5\r
+#define PRESCALER_DIV_128 6\r
+#define PRESCALER_DIV_256 7\r
+#define PRESCALER_DIV_512 8\r
+#define PRESCALER_DIV_1024 9\r
+\r
+/***************************************************************************//**\r
+ * There should be one instance of this structure for each instance of CoreTimer\r
+ * in your system. The function TMR_init() initializes this structure. It is\r
+ * used to identify the various CoreTimer hardware instances in your system.\r
+ * An initialized timer instance structure should be passed as first parameter to\r
+ * CoreTimer driver functions to identify which CoreTimer instance should perform\r
+ * the requested operation.\r
+ * Software using this driver should only need to create one single instance of \r
+ * this data structure for each hardware timer instance in the system.\r
+ */\r
+typedef struct __timer_instance_t\r
+{\r
+ addr_t base_address;\r
+} timer_instance_t;\r
+\r
+/***************************************************************************//**\r
+ * The function TMR_init() initializes the data structures and sets relevant\r
+ * CoreTimer registers. This function will prepare the Timer for use in a given\r
+ * hardware/software configuration. It should be called before any other Timer\r
+ * API functions.\r
+ * The timer will not start counting down immediately after this function is\r
+ * called. It is necessary to call TMR_start() to start the timer decrementing.\r
+ * The CoreTimer interrupt is disabled as part of this function.\r
+ *\r
+ * @param this_timer Pointer to a timer_instance_t structure holding all \r
+ * relevant data associated with the target timer hardware\r
+ * instance. This pointer will be used to identify the\r
+ * target CoreTimer hardware instance in subsequent calls\r
+ * to the CoreTimer functions.\r
+ * @param address Base address in the processor's memory map of the \r
+ * registers of the CoreTimer instance being initialized.\r
+ * @param mode This parameter is used to select the operating mode of\r
+ * the timer driver. This can be either TMR_CONTINUOUS_MODE\r
+ * or TMR_ONE_SHOT_MODE.\r
+ * @param prescale This parameter is used to select the prescaler divider\r
+ * used to divide down the clock used to decrement the\r
+ * timer\92s counter. This can be set using one of the \r
+ * PRESCALER_DIV_<n> definitions, where <n> is the\r
+ * divider\92s value. \r
+ * @param load_value This parameter is used to set the timer\92s load value\r
+ * from which the CoreTimer counter will decrement.\r
+ * In Continuous mode, this value will be used to reload \r
+ * the timer\92s counter whenever it reaches zero.\r
+ */\r
+void\r
+TMR_init\r
+(\r
+ timer_instance_t * this_timer,\r
+ addr_t address,\r
+ uint8_t mode,\r
+ uint32_t prescale,\r
+ uint32_t load_value\r
+);\r
+\r
+/***************************************************************************//**\r
+ * The function TMR_start() enables the timer to start counting down.\r
+ * This function only needs to be called once after the timer has been\r
+ * initialized through a call to TMR_init(). It does not need to be called after\r
+ * each call to TMR_reload() when the timer is used in one-shot mode.\r
+ *\r
+ * @param this_timer Pointer to a timer_instance_t structure holding all \r
+ * relevant data associated with the target timer hardware\r
+ * instance. This pointer is used to identify the target\r
+ * CoreTimer hardware instance.\r
+ */\r
+void\r
+TMR_start\r
+(\r
+ timer_instance_t * this_timer\r
+);\r
+\r
+/***************************************************************************//**\r
+ * The function TMR_stop() stops the timer counting down. It can be used to \r
+ * stop interrupts from being generated when continuous mode is used and\r
+ * interrupts must be paused from being generated.\r
+ *\r
+ * @param this_timer Pointer to a timer_instance_t structure holding all \r
+ * relevant data associated with the target timer hardware\r
+ * instance. This pointer is used to identify the target\r
+ * CoreTimer hardware instance.\r
+ */\r
+void\r
+TMR_stop\r
+(\r
+ timer_instance_t * this_timer\r
+);\r
+\r
+/***************************************************************************//**\r
+ * The function TMR_enable_int() enables the timer interrupt. A call to this\r
+ * function will allow the interrupt signal coming out of CoreTimer to be\r
+ * asserted. \r
+ *\r
+ * @param this_timer Pointer to a timer_instance_t structure holding all \r
+ * relevant data associated with the target timer hardware\r
+ * instance. This pointer is used to identify the target\r
+ * CoreTimer hardware instance.\r
+ */\r
+void\r
+TMR_enable_int\r
+(\r
+ timer_instance_t * this_timer\r
+);\r
+\r
+/***************************************************************************//**\r
+ * The function TMR_clear_int() clears the timer interrupt. This function should\r
+ * be called within the interrupt handler servicing interrupts from the timer.\r
+ * Failure to clear the timer interrupt will result in the interrupt signal\r
+ * generating from CoreTimer to remain asserted. This assertion may cause the\r
+ * interrupt service routine to be continuously called, causing the system to\r
+ * lock up.\r
+ *\r
+ * @param this_timer Pointer to a timer_instance_t structure holding all \r
+ * relevant data associated with the target timer hardware\r
+ * instance. This pointer is used to identify the target\r
+ * CoreTimer hardware instance.\r
+ */\r
+void\r
+TMR_clear_int\r
+(\r
+ timer_instance_t * this_timer\r
+);\r
+\r
+/***************************************************************************//**\r
+ * The TMR_current_value() function returns the current value of the counter.\r
+ *\r
+ * @param this_timer Pointer to a timer_instance_t structure holding all \r
+ * relevant data associated with the target timer hardware\r
+ * instance. This pointer is used to identify the target\r
+ * CoreTimer hardware instance.\r
+ *\r
+ * @return Returns the current value of the timer counter value.\r
+ */\r
+uint32_t\r
+TMR_current_value\r
+(\r
+ timer_instance_t * this_timer\r
+);\r
+\r
+/***************************************************************************//**\r
+ * The TMR_reload() function is used in one-shot mode. It reloads the timer\r
+ * counter with the values passed as parameter. This will result in an interrupt\r
+ * being generated when the timer counter reaches 0 if interrupt is enabled.\r
+ * \r
+ * @param this_timer Pointer to a timer_instance_t structure holding all \r
+ * relevant data associated with the target timer hardware\r
+ * instance. This pointer is used to identify the target\r
+ * CoreTimer hardware instance.\r
+ * @param load_value This parameter sets the value from which the CoreTimer\r
+ * counter will decrement. \r
+ */\r
+void TMR_reload\r
+(\r
+ timer_instance_t * this_timer,\r
+ uint32_t load_value\r
+);\r
+ \r
+#endif /* CORE_TIMER_H_ */\r
--- /dev/null
+/*******************************************************************************\r
+ * (c) Copyright 2007-2015 Microsemi SoC Products Group. All rights reserved.\r
+ * \r
+ * SVN $Revision: 7967 $\r
+ * SVN $Date: 2015-10-09 18:48:26 +0530 (Fri, 09 Oct 2015) $\r
+ */\r
+\r
+#ifndef __CORE_TIMER_REGISTERS\r
+#define __CORE_TIMER_REGISTERS 1\r
+\r
+/*------------------------------------------------------------------------------\r
+ * TimerLoad register details\r
+ */\r
+#define TimerLoad_REG_OFFSET 0x00\r
+\r
+/*\r
+ * LoadValue bits.\r
+ */\r
+#define LoadValue_OFFSET 0x00\r
+#define LoadValue_MASK 0xFFFFFFFF\r
+#define LoadValue_SHIFT 0\r
+\r
+/*------------------------------------------------------------------------------\r
+ * TimerValue register details\r
+ */\r
+#define TimerValue_REG_OFFSET 0x04\r
+\r
+/*\r
+ * CurrentValue bits.\r
+ */\r
+#define CurrentValue_OFFSET 0x04\r
+#define CurrentValue_MASK 0xFFFFFFFF\r
+#define CurrentValue_SHIFT 0\r
+\r
+/*------------------------------------------------------------------------------\r
+ * TimerControl register details\r
+ */\r
+#define TimerControl_REG_OFFSET 0x08\r
+\r
+/*\r
+ * TimerEnable bits.\r
+ */\r
+#define TimerEnable_OFFSET 0x08\r
+#define TimerEnable_MASK 0x00000001\r
+#define TimerEnable_SHIFT 0\r
+\r
+/*\r
+ * InterruptEnable bits.\r
+ */\r
+#define InterruptEnable_OFFSET 0x08\r
+#define InterruptEnable_MASK 0x00000002\r
+#define InterruptEnable_SHIFT 1\r
+\r
+/*\r
+ * TimerMode bits.\r
+ */\r
+#define TimerMode_OFFSET 0x08\r
+#define TimerMode_MASK 0x00000004\r
+#define TimerMode_SHIFT 2\r
+\r
+/*------------------------------------------------------------------------------\r
+ * TimerPrescale register details\r
+ */\r
+#define TimerPrescale_REG_OFFSET 0x0C\r
+\r
+/*\r
+ * Prescale bits.\r
+ */\r
+#define Prescale_OFFSET 0x0C\r
+#define Prescale_MASK 0x0000000F\r
+#define Prescale_SHIFT 0\r
+\r
+/*------------------------------------------------------------------------------\r
+ * TimerIntClr register details\r
+ */\r
+#define TimerIntClr_REG_OFFSET 0x10\r
+\r
+/*\r
+ * TimerIntClr bits.\r
+ */\r
+#define TimerIntClr_OFFSET 0x10\r
+#define TimerIntClr_MASK 0xFFFFFFFF\r
+#define TimerIntClr_SHIFT 0\r
+\r
+/*------------------------------------------------------------------------------\r
+ * TimerRIS register details\r
+ */\r
+#define TimerRIS_REG_OFFSET 0x14\r
+\r
+/*\r
+ * RawTimerInterrupt bits.\r
+ */\r
+#define RawTimerInterrupt_OFFSET 0x14\r
+#define RawTimerInterrupt_MASK 0x00000001\r
+#define RawTimerInterrupt_SHIFT 0\r
+\r
+/*------------------------------------------------------------------------------\r
+ * TimerMIS register details\r
+ */\r
+#define TimerMIS_REG_OFFSET 0x18\r
+\r
+/*\r
+ * TimerInterrupt bits.\r
+ */\r
+#define TimerInterrupt_OFFSET 0x18\r
+#define TimerInterrupt_MASK 0x00000001\r
+#define TimerInterrupt_SHIFT 0\r
+\r
+#endif /* __CORE_TIMER_REGISTERS */\r
--- /dev/null
+/*******************************************************************************\r
+ * (c) Copyright 2007-2017 Microsemi SoC Products Group. All rights reserved.\r
+ * \r
+ * CoreUARTapb driver implementation. See file "core_uart_apb.h" for a\r
+ * description of the functions implemented in this file.\r
+ * \r
+ * SVN $Revision: 9082 $\r
+ * SVN $Date: 2017-04-28 11:51:36 +0530 (Fri, 28 Apr 2017) $\r
+ */\r
+#include "hal.h"\r
+#include "coreuartapb_regs.h"\r
+#include "core_uart_apb.h"\r
+#include "hal_assert.h"\r
+\r
+#ifdef __cplusplus\r
+extern "C" {\r
+#endif\r
+\r
+#define NULL_INSTANCE ( ( UART_instance_t* ) 0 )\r
+#define NULL_BUFFER ( ( uint8_t* ) 0 )\r
+\r
+#define MAX_LINE_CONFIG ( ( uint8_t )( DATA_8_BITS | ODD_PARITY ) )\r
+#define MAX_BAUD_VALUE ( ( uint16_t )( 0x1FFF ) )\r
+#define STATUS_ERROR_MASK ( ( uint8_t )( STATUS_PARITYERR_MASK | \\r
+ STATUS_OVERFLOW_MASK | \\r
+ STATUS_FRAMERR_MASK ) )\r
+#define BAUDVALUE_LSB ( (uint16_t) (0x00FF) )\r
+#define BAUDVALUE_MSB ( (uint16_t) (0xFF00) )\r
+#define BAUDVALUE_SHIFT ( (uint8_t) (5) )\r
+\r
+#define STATUS_ERROR_OFFSET STATUS_PARITYERR_SHIFT \r
+\r
+/***************************************************************************//**\r
+ * UART_init()\r
+ * See "core_uart_apb.h" for details of how to use this function.\r
+ */\r
+void\r
+UART_init\r
+(\r
+ UART_instance_t * this_uart,\r
+ addr_t base_addr,\r
+ uint16_t baud_value,\r
+ uint8_t line_config\r
+)\r
+{\r
+ uint8_t rx_full;\r
+ \r
+ HAL_ASSERT( this_uart != NULL_INSTANCE )\r
+ HAL_ASSERT( line_config <= MAX_LINE_CONFIG )\r
+ HAL_ASSERT( baud_value <= MAX_BAUD_VALUE )\r
+\r
+ if( ( this_uart != NULL_INSTANCE ) &&\r
+ ( line_config <= MAX_LINE_CONFIG ) &&\r
+ ( baud_value <= MAX_BAUD_VALUE ) )\r
+ {\r
+ /*\r
+ * Store lower 8-bits of baud value in CTRL1.\r
+ */\r
+ HAL_set_8bit_reg( base_addr, CTRL1, (uint_fast8_t)(baud_value &\r
+ BAUDVALUE_LSB ) );\r
+ \r
+ /*\r
+ * Extract higher 5-bits of baud value and store in higher 5-bits \r
+ * of CTRL2, along with line configuration in lower 3 three bits.\r
+ */\r
+ HAL_set_8bit_reg( base_addr, CTRL2, (uint_fast8_t)line_config | \r
+ (uint_fast8_t)((baud_value &\r
+ BAUDVALUE_MSB) >> BAUDVALUE_SHIFT ) );\r
+ \r
+ this_uart->base_address = base_addr;\r
+#ifndef NDEBUG\r
+ {\r
+ uint8_t config;\r
+ uint8_t temp;\r
+ uint16_t baud_val;\r
+ baud_val = HAL_get_8bit_reg( this_uart->base_address, CTRL1 );\r
+ config = HAL_get_8bit_reg( this_uart->base_address, CTRL2 );\r
+ /*\r
+ * To resolve operator precedence between & and <<\r
+ */\r
+ temp = ( config & (uint8_t)(CTRL2_BAUDVALUE_MASK ) );\r
+ baud_val |= (uint16_t)( (uint16_t)(temp) << BAUDVALUE_SHIFT );\r
+ config &= (uint8_t)(~CTRL2_BAUDVALUE_MASK);\r
+ HAL_ASSERT( baud_val == baud_value );\r
+ HAL_ASSERT( config == line_config );\r
+ } \r
+#endif\r
+ \r
+ /*\r
+ * Flush the receive FIFO of data that may have been received before the\r
+ * driver was initialized.\r
+ */\r
+ rx_full = HAL_get_8bit_reg( this_uart->base_address, STATUS ) &\r
+ STATUS_RXFULL_MASK;\r
+ while ( rx_full )\r
+ {\r
+ HAL_get_8bit_reg( this_uart->base_address, RXDATA );\r
+ rx_full = HAL_get_8bit_reg( this_uart->base_address, STATUS ) &\r
+ STATUS_RXFULL_MASK;\r
+ }\r
+\r
+ /*\r
+ * Clear status of the UART instance.\r
+ */\r
+ this_uart->status = (uint8_t)0;\r
+ }\r
+}\r
+\r
+/***************************************************************************//**\r
+ * UART_send()\r
+ * See "core_uart_apb.h" for details of how to use this function.\r
+ */\r
+void\r
+UART_send\r
+(\r
+ UART_instance_t * this_uart,\r
+ const uint8_t * tx_buffer,\r
+ size_t tx_size\r
+)\r
+{\r
+ size_t char_idx;\r
+ uint8_t tx_ready;\r
+\r
+ HAL_ASSERT( this_uart != NULL_INSTANCE )\r
+ HAL_ASSERT( tx_buffer != NULL_BUFFER )\r
+ HAL_ASSERT( tx_size > 0 )\r
+ \r
+ if( (this_uart != NULL_INSTANCE) &&\r
+ (tx_buffer != NULL_BUFFER) &&\r
+ (tx_size > (size_t)0) )\r
+ {\r
+ for ( char_idx = (size_t)0; char_idx < tx_size; char_idx++ )\r
+ {\r
+ /* Wait for UART to become ready to transmit. */\r
+ do {\r
+ tx_ready = HAL_get_8bit_reg( this_uart->base_address, STATUS ) &\r
+ STATUS_TXRDY_MASK;\r
+ } while ( !tx_ready );\r
+ /* Send next character in the buffer. */\r
+ HAL_set_8bit_reg( this_uart->base_address, TXDATA,\r
+ (uint_fast8_t)tx_buffer[char_idx] );\r
+ }\r
+ }\r
+}\r
+\r
+/***************************************************************************//**\r
+ * UART_fill_tx_fifo()\r
+ * See "core_uart_apb.h" for details of how to use this function.\r
+ */\r
+size_t\r
+UART_fill_tx_fifo\r
+(\r
+ UART_instance_t * this_uart,\r
+ const uint8_t * tx_buffer,\r
+ size_t tx_size\r
+)\r
+{\r
+ uint8_t tx_ready;\r
+ size_t size_sent = 0u;\r
+ \r
+ HAL_ASSERT( this_uart != NULL_INSTANCE )\r
+ HAL_ASSERT( tx_buffer != NULL_BUFFER )\r
+ HAL_ASSERT( tx_size > 0 )\r
+ \r
+ /* Fill the UART's Tx FIFO until the FIFO is full or the complete input \r
+ * buffer has been written. */\r
+ if( (this_uart != NULL_INSTANCE) &&\r
+ (tx_buffer != NULL_BUFFER) &&\r
+ (tx_size > 0u) )\r
+ {\r
+ tx_ready = HAL_get_8bit_reg( this_uart->base_address, STATUS ) &\r
+ STATUS_TXRDY_MASK;\r
+ if ( tx_ready )\r
+ {\r
+ do {\r
+ HAL_set_8bit_reg( this_uart->base_address, TXDATA,\r
+ (uint_fast8_t)tx_buffer[size_sent] );\r
+ size_sent++;\r
+ tx_ready = HAL_get_8bit_reg( this_uart->base_address, STATUS ) &\r
+ STATUS_TXRDY_MASK;\r
+ } while ( (tx_ready) && ( size_sent < tx_size ) );\r
+ }\r
+ } \r
+ return size_sent;\r
+}\r
+\r
+/***************************************************************************//**\r
+ * UART_get_rx()\r
+ * See "core_uart_apb.h" for details of how to use this function.\r
+ */\r
+size_t\r
+UART_get_rx\r
+(\r
+ UART_instance_t * this_uart,\r
+ uint8_t * rx_buffer,\r
+ size_t buff_size\r
+)\r
+{\r
+ uint8_t new_status;\r
+ uint8_t rx_full;\r
+ size_t rx_idx = 0u;\r
+ \r
+ HAL_ASSERT( this_uart != NULL_INSTANCE )\r
+ HAL_ASSERT( rx_buffer != NULL_BUFFER )\r
+ HAL_ASSERT( buff_size > 0 )\r
+ \r
+ if( (this_uart != NULL_INSTANCE) &&\r
+ (rx_buffer != NULL_BUFFER) &&\r
+ (buff_size > 0u) )\r
+ {\r
+ rx_idx = 0u;\r
+ new_status = HAL_get_8bit_reg( this_uart->base_address, STATUS );\r
+ this_uart->status |= new_status;\r
+ rx_full = new_status & STATUS_RXFULL_MASK;\r
+ while ( ( rx_full ) && ( rx_idx < buff_size ) )\r
+ {\r
+ rx_buffer[rx_idx] = HAL_get_8bit_reg( this_uart->base_address,\r
+ RXDATA );\r
+ rx_idx++;\r
+ new_status = HAL_get_8bit_reg( this_uart->base_address, STATUS );\r
+ this_uart->status |= new_status;\r
+ rx_full = new_status & STATUS_RXFULL_MASK;\r
+ }\r
+ }\r
+ return rx_idx;\r
+}\r
+\r
+/***************************************************************************//**\r
+ * UART_polled_tx_string()\r
+ * See "core_uart_apb.h" for details of how to use this function.\r
+ */\r
+void \r
+UART_polled_tx_string\r
+( \r
+ UART_instance_t * this_uart, \r
+ const uint8_t * p_sz_string\r
+)\r
+{\r
+ uint32_t char_idx;\r
+ uint8_t tx_ready;\r
+\r
+ HAL_ASSERT( this_uart != NULL_INSTANCE )\r
+ HAL_ASSERT( p_sz_string != NULL_BUFFER )\r
+ \r
+ if( ( this_uart != NULL_INSTANCE ) && ( p_sz_string != NULL_BUFFER ) )\r
+ {\r
+ char_idx = 0U;\r
+ while( 0U != p_sz_string[char_idx] )\r
+ {\r
+ /* Wait for UART to become ready to transmit. */\r
+ do {\r
+ tx_ready = HAL_get_8bit_reg( this_uart->base_address, STATUS ) &\r
+ STATUS_TXRDY_MASK;\r
+ } while ( !tx_ready );\r
+ /* Send next character in the buffer. */\r
+ HAL_set_8bit_reg( this_uart->base_address, TXDATA,\r
+ (uint_fast8_t)p_sz_string[char_idx] );\r
+ char_idx++;\r
+ }\r
+ }\r
+}\r
+\r
+/***************************************************************************//**\r
+ * UART_get_rx_status()\r
+ * See "core_uart_apb.h" for details of how to use this function.\r
+ */\r
+uint8_t\r
+UART_get_rx_status\r
+(\r
+ UART_instance_t * this_uart\r
+)\r
+{\r
+ uint8_t status = UART_APB_INVALID_PARAM;\r
+\r
+ HAL_ASSERT( this_uart != NULL_INSTANCE )\r
+ /*\r
+ * Extract UART error status and place in lower bits of "status".\r
+ * Bit 0 - Parity error status\r
+ * Bit 1 - Overflow error status\r
+ * Bit 2 - Frame error status\r
+ */\r
+ if( this_uart != NULL_INSTANCE )\r
+ {\r
+ status = ( ( this_uart->status & STATUS_ERROR_MASK ) >> \r
+ STATUS_ERROR_OFFSET );\r
+ /*\r
+ * Clear the sticky status for this instance.\r
+ */\r
+ this_uart->status = (uint8_t)0;\r
+ }\r
+ return status;\r
+}\r
+\r
+#ifdef __cplusplus\r
+}\r
+#endif\r
--- /dev/null
+/*******************************************************************************\r
+ * (c) Copyright 2007-2017 Microsemi SoC Products Group. All rights reserved.\r
+ * \r
+ * This file contains the application programming interface for the CoreUARTapb\r
+ * bare metal driver.\r
+ * \r
+ * SVN $Revision: 9082 $\r
+ * SVN $Date: 2017-04-28 11:51:36 +0530 (Fri, 28 Apr 2017) $\r
+ */\r
+/*=========================================================================*//**\r
+ @mainpage CoreUARTapb Bare Metal Driver.\r
+\r
+ @section intro_sec Introduction\r
+ CoreUARTapb is an implementation of the Universal Asynchronous \r
+ Receiver/Transmitter aimed at a minimal FPGA tile usage within an Microsemi\r
+ FPGA. The CoreUARTapb bare metal software driver is designed for use in \r
+ systems with no operating system.\r
+\r
+ The CoreUARTapb driver provides functions for basic polled transmitting and \r
+ receiving operations. It also provides functions allowing use of the \r
+ CoreUARTapb in interrupt-driven mode, but leaves the management of interrupts \r
+ to the calling application, as interrupt enabling and disabling cannot be \r
+ controlled through the CoreUARTapb registers. The CoreUARTapb driver is \r
+ provided as C source code.\r
+\r
+ @section driver_configuration Driver Configuration\r
+ Your application software should configure the CoreUARTapb driver, through \r
+ calls to the UART_init() function for each CoreUARTapb instance in the \r
+ hardware design. The configuration parameters include the CoreUARTapb \r
+ hardware instance base address and other runtime parameters, such as baud \r
+ rate, bit width, and parity. No CoreUARTapb hardware configuration parameters \r
+ are needed by the driver, apart from the CoreUARTapb hardware instance base \r
+ address. Hence, no additional configuration files are required to use the driver.\r
+\r
+ A CoreUARTapb hardware instance can be generated with fixed baud value, \r
+ character size and parity configuration settings as part of the hardware flow. \r
+ The baud_value and line_config parameter values passed to the UART_init() \r
+ function will not have any effect if fixed values were selected for the \r
+ baud value, character size and parity in the hardware configuration of \r
+ CoreUARTapb. When fixed values are selected for these hardware configuration \r
+ parameters, the driver cannot overwrite the fixed values in the CoreUARTapb \r
+ control registers, CTRL1 and CTRL2.\r
+\r
+ @section theory_op Theory of Operation\r
+ The CoreUARTapb software driver is designed to allow the control of multiple \r
+ instances of CoreUARTapb. Each instance of CoreUARTapb in the hardware design \r
+ is associated with a single instance of the UART_instance_t structure in the \r
+ software. You need to allocate memory for one unique UART_instance_t \r
+ structure instance for each CoreUARTapb hardware instance. The contents of \r
+ these data structures are initialized during calls to function UART_init(). \r
+ A pointer to the structure is passed to subsequent driver functions in order\r
+ to identify the CoreUARTapb hardware instance you wish to perform the \r
+ requested operation on.\r
+ \r
+ Note: Do not attempt to directly manipulate the content of UART_instance_t \r
+ structures. This structure is only intended to be modified by the driver \r
+ function.\r
+\r
+ The driver can be used to transmit and receive data once initialized. \r
+ Transmit can be performed using the UART_send() function. This function\r
+ is blocking, meaning that it will only return once the data passed to \r
+ the function has been sent to the CoreUARTapb hardware. Data received \r
+ by the CoreUARTapb hardware can be read by the user application using \r
+ the UART_get_rx() function.\r
+\r
+ The function UART_fill_tx_fifo() is also provided to be used as part of \r
+ interrupt-driven transmit. This function fills the CoreUARTapb hardware \r
+ transmit FIFO with the content of a data buffer passed as a parameter before \r
+ returning. The control of the interrupts must be implemented outside the \r
+ driver as the CoreUARTapb hardware does not provide the ability to enable \r
+ or disable its interrupt sources.\r
+\r
+ The function UART_polled_tx_string() is provided to transmit a NULL \r
+ terminated string in polled mode. This function is blocking, meaning that it \r
+ will only return once the data passed to the function has been sent to the \r
+ CoreUARTapb hardware.\r
+\r
+ The function UART_get_rx_status() returns the error status of the CoreUARTapb\r
+ receiver. This can be used by applications to take appropriate action in case\r
+ of receiver errors.\r
+*//*=========================================================================*/\r
+#ifndef __CORE_UART_APB_H\r
+#define __CORE_UART_APB_H 1\r
+\r
+#include "cpu_types.h"\r
+\r
+#ifdef __cplusplus\r
+extern "C" {\r
+#endif\r
+\r
+/***************************************************************************//**\r
+ * Data bits length defines:\r
+ */\r
+#define DATA_7_BITS 0x00u\r
+#define DATA_8_BITS 0x01u\r
+\r
+/***************************************************************************//**\r
+ * Parity defines:\r
+ */\r
+#define NO_PARITY 0x00u\r
+#define EVEN_PARITY 0x02u\r
+#define ODD_PARITY 0x06u\r
+\r
+/***************************************************************************//**\r
+ * Error Status definitions:\r
+ */\r
+#define UART_APB_PARITY_ERROR 0x01u\r
+#define UART_APB_OVERFLOW_ERROR 0x02u\r
+#define UART_APB_FRAMING_ERROR 0x04u\r
+#define UART_APB_NO_ERROR 0x00u\r
+#define UART_APB_INVALID_PARAM 0xFFu\r
+\r
+/***************************************************************************//**\r
+ * UART_instance_t\r
+ * \r
+ * There should be one instance of this structure for each instance of CoreUARTapb\r
+ * in your system. This structure instance is used to identify the various UARTs\r
+ * in a system and should be passed as first parameter to UART functions to \r
+ * identify which UART should perform the requested operation. The 'status' \r
+ * element in the structure is used to provide sticky status information. \r
+ */\r
+typedef struct\r
+{\r
+ addr_t base_address;\r
+ uint8_t status;\r
+} UART_instance_t;\r
+\r
+/***************************************************************************//**\r
+ * The function UART_init() initializes the UART with the configuration passed \r
+ * as parameters. The configuration parameters are the baud_value used to \r
+ * generate the baud rate and the line configuration (bit length and parity).\r
+ *\r
+ * @param this_uart The this_uart parameter is a pointer to a UART_instance_t\r
+ * structure which holds all data regarding this instance of\r
+ * the CoreUARTapb. This pointer will be used to identify \r
+ * the target CoreUARTapb hardware instance in subsequent \r
+ * calls to the CoreUARTapb functions.\r
+ * @param base_addr The base_address parameter is the base address in the \r
+ * processor's memory map for the registers of the \r
+ * CoreUARTapb instance being initialized.\r
+ * @param baud_value The baud_value parameter is used to select the baud rate \r
+ * for the UART. The baud value is calculated from the \r
+ * frequency of the system clock in hertz and the desired \r
+ * baud rate using the following equation: \r
+ * \r
+ * baud_value = (clock /(baud_rate * 16)) - 1.\r
+ * \r
+ * The baud_value parameter must be a value in the range 0 \r
+ * to 8191 (or 0x0000 to 0x1FFF).\r
+ * @param line_config This parameter is the line configuration specifying the \r
+ * bit length and parity settings. This is a logical OR of:\r
+ * - DATA_7_BITS\r
+ * - DATA_8_BITS\r
+ * - NO_PARITY\r
+ * - EVEN_PARITY\r
+ * - ODD_PARITY\r
+ * For example, 8 bits even parity would be specified as \r
+ * (DATA_8_BITS | EVEN_PARITY). \r
+ * @return This function does not return a value.\r
+ * Example:\r
+ * @code\r
+ * #define BAUD_VALUE_57600 25\r
+ * \r
+ * #define COREUARTAPB0_BASE_ADDR 0xC3000000UL\r
+ * \r
+ * UART_instance_t g_uart;\r
+ * int main()\r
+ * {\r
+ * UART_init(&g_uart, COREUARTAPB0_BASE_ADDR, \r
+ BAUD_VALUE_57600, (DATA_8_BITS | EVEN_PARITY));\r
+ * }\r
+ * @endcode\r
+ */\r
+void\r
+UART_init\r
+(\r
+ UART_instance_t * this_uart,\r
+ addr_t base_addr,\r
+ uint16_t baud_value,\r
+ uint8_t line_config\r
+);\r
+\r
+/***************************************************************************//**\r
+ * The function UART_send() is used to transmit data. It transfers the contents\r
+ * of the transmitter data buffer, passed as a function parameter, into the \r
+ * UART's hardware transmitter FIFO. It returns when the full content of the \r
+ * transmitter data buffer has been transferred to the UART's transmitter FIFO. \r
+ *\r
+ * Note: you cannot assume that the data you are sending using this function has\r
+ * been received at the other end by the time this function returns. The actual\r
+ * transmit over the serial connection will still be taking place at the time of\r
+ * the function return. It is safe to release or reuse the memory used as the\r
+ * transmit buffer once this function returns.\r
+ *\r
+ * @param this_uart The this_uart parameter is a pointer to a \r
+ * UART_instance_t structure which holds all data regarding \r
+ * this instance of the CoreUARTapbUART.\r
+ * @param tx_buffer The tx_buffer parameter is a pointer to a buffer \r
+ * containing the data to be transmitted.\r
+ * @param tx_size The tx_size parameter is the size, in bytes, of \r
+ * the data to be transmitted.\r
+ *\r
+ * @return This function does not return a value.\r
+ *\r
+ * Example:\r
+ * @code\r
+ * uint8_t testmsg1[] = {"\n\r\n\r\n\rUART_send() test message 1"};\r
+ * UART_send(&g_uart,(const uint8_t *)&testmsg1,sizeof(testmsg1));\r
+ * @endcode\r
+ */\r
+void\r
+UART_send\r
+(\r
+ UART_instance_t * this_uart,\r
+ const uint8_t * tx_buffer,\r
+ size_t tx_size\r
+);\r
+\r
+/***************************************************************************//**\r
+ * The function UART_fill_tx_fifo() fills the UART's transmitter hardware FIFO \r
+ * with the data found in the transmitter buffer that is passed in as a \r
+ * function parameter. The function returns either when the FIFO is full or \r
+ * when the complete contents of the transmitter buffer have been copied into \r
+ * the FIFO. It returns the number of bytes copied into the UART's transmitter\r
+ * hardware FIFO. This function is intended to be used as part of \r
+ * interrupt-driven transmission.\r
+ *\r
+ * Note: You cannot assume that the data you transmit using this function has \r
+ * been received at the other end by the time this function returns. \r
+ * The actual transmission over the serial connection will still be \r
+ * taking place at the time of the function return. \r
+ *\r
+ * @param this_uart The this_uart parameter is a pointer to a UART_instance_t\r
+ * structure which holds all data regarding this instance of\r
+ * the UART.\r
+ * @param tx_buffer The tx_buffer parameter is a pointer to a buffer \r
+ * containing the data to be transmitted.\r
+ * @param tx_size The tx_size parameter is the size in bytes, of the data \r
+ * to be transmitted.\r
+ * @return This function returns the number of bytes copied \r
+ * into the UART's transmitter hardware FIFO. \r
+ *\r
+ * Example:\r
+ * @code\r
+ * void send_using_interrupt\r
+ * (\r
+ * uint8_t * pbuff,\r
+ * size_t tx_size\r
+ * )\r
+ * {\r
+ * size_t size_in_fifo;\r
+ * size_in_fifo = UART_fill_tx_fifo( &g_uart, pbuff, tx_size );\r
+ * }\r
+ * @endcode\r
+ */\r
+size_t\r
+UART_fill_tx_fifo\r
+(\r
+ UART_instance_t * this_uart,\r
+ const uint8_t * tx_buffer,\r
+ size_t tx_size\r
+);\r
+\r
+/***************************************************************************//**\r
+ * The function UART_get_rx() reads the content of the UART's receiver hardware \r
+ * FIFO and stores it in the receiver buffer that is passed in as a function \r
+ * parameter. It copies either the full contents of the FIFO into the receiver \r
+ * buffer, or just enough data from the FIFO to fill the receiver buffer, \r
+ * dependent upon the size of the receiver buffer. The size of the receiver \r
+ * buffer is passed in as a function parameter. UART_get_rx() returns the number\r
+ * of bytes copied into the receiver buffer. If no data was received at the time\r
+ * the function is called, the function returns 0.\r
+ *\r
+ * Note: This function reads and accumulates the receiver status of the \r
+ * CoreUARTapb instance before reading each byte from the receiver's \r
+ * data register/FIFO. This allows the driver to maintain a sticky \r
+ * record of any receiver errors that occur as the UART receives each \r
+ * data byte; receiver errors would otherwise be lost after each read \r
+ * from the receiver's data register. A call to the UART_get_rx_status()\r
+ * function returns any receiver errors accumulated during the execution\r
+ * of the UART_get_rx() function.\r
+ * Note: When FIFO mode is disabled in the CoreUARTapb hardware configuration,\r
+ * the driver accumulates a sticky record of any parity errors, framing \r
+ * errors or overflow errors. When FIFO mode is enabled, the driver \r
+ * accumulates a sticky record of overflow errors only; in this case \r
+ * interrupts must be used to handle parity errors or framing errors.\r
+ *\r
+ * @param this_uart The this_uart parameter is a pointer to a UART_instance_t \r
+ * structure which holds all data regarding this instance of \r
+ * the UART.\r
+ * @param rx_buffer The rx_buffer parameter is a pointer to a buffer where the \r
+ * received data will be copied.\r
+ * @param buff_size The buff_size parameter is the size of the receive buffer \r
+ * in bytes.\r
+ * @return This function returns the number of bytes copied into the \r
+ * receive buffer.\r
+ *\r
+ * Example:\r
+ * @code\r
+ * #define MAX_RX_DATA_SIZE 256\r
+ * \r
+ * uint8_t rx_data[MAX_RX_DATA_SIZE];\r
+ * uint8_t rx_size = 0;\r
+ * \r
+ * rx_size = UART_get_rx( &g_uart, rx_data, sizeof(rx_data) );\r
+ * @endcode\r
+ */\r
+size_t\r
+UART_get_rx\r
+(\r
+ UART_instance_t * this_uart,\r
+ uint8_t * rx_buffer,\r
+ size_t buff_size\r
+);\r
+\r
+/***************************************************************************//**\r
+ * The function UART_polled_tx_string() is used to transmit a NULL ('\0') \r
+ * terminated string. Internally, it polls for the transmit ready status and\r
+ * transfers the text starting at the address pointed to by p_sz_string into\r
+ * the UART's hardware transmitter FIFO. It is a blocking function and returns\r
+ * only when the complete string has been transferred to the UART's transmit \r
+ * FIFO.\r
+ *\r
+ * Note: You cannot assume that the data you transmit using this function \r
+ * has been received at the other end by the time this function \r
+ * returns. The actual transmission over the serial connection will\r
+ * still be taking place at the time of the function return.\r
+ *\r
+ * @param this_uart The this_uart parameter is a pointer to a \r
+ * UART_instance_t structure which holds\r
+ * all data regarding this instance of the UART.\r
+ * @param p_sz_string The p_sz_string parameter is a pointer to a buffer\r
+ * containing the NULL ('\0') terminated string to be \r
+ * transmitted.\r
+ * @return This function does not return a value.\r
+ *\r
+ * Example:\r
+ * @code\r
+ * uint8_t testmsg1[] = {"\r\n\r\nUART_polled_tx_string() test message 1\0"};\r
+ * UART_polled_tx_string(&g_uart,(const uint8_t *)&testmsg1);\r
+ * @endcode\r
+ */\r
+void \r
+UART_polled_tx_string\r
+( \r
+ UART_instance_t * this_uart, \r
+ const uint8_t * p_sz_string\r
+);\r
+\r
+/***************************************************************************//**\r
+ * The UART_get_rx_status() function returns the receiver error status of the \r
+ * CoreUARTapb instance. It reads both the current error status of the receiver\r
+ * and the accumulated error status from preceding calls to the UART_get_rx() \r
+ * function and combines them using a bitwise OR. It returns the cumulative \r
+ * parity, framing and overflow error status of the receiver, since the \r
+ * previous call to UART_get_rx_status(), as an 8-bit encoded value.\r
+ *\r
+ * Note: The UART_get_rx() function reads and accumulates the receiver status \r
+ * of the CoreUARTapb instance before reading each byte from the \r
+ * receiver's data register/FIFO. The driver maintains a sticky record \r
+ * of the cumulative error status, which persists after the \r
+ * UART_get_rx() function returns. The UART_get_rx_status() function \r
+ * clears this accumulated record of receiver errors before returning.\r
+ * \r
+ * @param this_uart The this_uart parameter is a pointer to a UART_instance_t\r
+ * structure which holds all data regarding this instance \r
+ * of the UART.\r
+ * @return This function returns the UART receiver error status as \r
+ * an 8-bit encoded value. The returned value is 0 if no \r
+ * receiver errors occurred. The driver provides a set of \r
+ * bit mask constants which should be compared with and/or\r
+ * used to mask the returned value to determine the \r
+ * receiver error status. \r
+ * When the return value is compared to the following bit \r
+ * masks, a non-zero result indicates that the \r
+ * corresponding error occurred:\r
+ * UART_APB_PARITY_ERROR (bit mask = 0x01)\r
+ * UART_APB_OVERFLOW_ERROR (bit mask = 0x02)\r
+ * UART_APB_FRAMING_ERROR (bit mask = 0x04)\r
+ * When the return value is compared to the following bit \r
+ * mask, a non-zero result indicates that no error occurred:\r
+ * UART_APB_NO_ERROR (0x00)\r
+ *\r
+ * Example:\r
+ * @code\r
+ * UART_instance_t g_uart;\r
+ * uint8_t rx_data[MAX_RX_DATA_SIZE];\r
+ * uint8_t err_status;\r
+ * err_status = UART_get_err_status(&g_uart);\r
+ * \r
+ * if(UART_APB_NO_ERROR == err_status )\r
+ * {\r
+ * rx_size = UART_get_rx( &g_uart, rx_data, MAX_RX_DATA_SIZE );\r
+ * }\r
+ * @endcode\r
+ */\r
+uint8_t\r
+UART_get_rx_status\r
+(\r
+ UART_instance_t * this_uart\r
+);\r
+\r
+#ifdef __cplusplus\r
+}\r
+#endif\r
+\r
+#endif /* __CORE_UART_APB_H */\r
--- /dev/null
+/*******************************************************************************\r
+ * (c) Copyright 2007-2017 Microsemi SoC Products Group. All rights reserved.\r
+ * \r
+ * SVN $Revision: 9082 $\r
+ * SVN $Date: 2017-04-28 11:51:36 +0530 (Fri, 28 Apr 2017) $\r
+ */\r
+\r
+#ifndef __CORE_UART_APB_REGISTERS\r
+#define __CORE_UART_APB_REGISTERS 1\r
+\r
+#ifdef __cplusplus\r
+extern "C" {\r
+#endif\r
+\r
+/*------------------------------------------------------------------------------\r
+ * TxData register details\r
+ */\r
+#define TXDATA_REG_OFFSET 0x0u\r
+\r
+/*\r
+ * TxData bits.\r
+ */\r
+#define TXDATA_OFFSET 0x0u\r
+#define TXDATA_MASK 0xFFu\r
+#define TXDATA_SHIFT 0u\r
+\r
+/*------------------------------------------------------------------------------\r
+ * RxData register details\r
+ */\r
+#define RXDATA_REG_OFFSET 0x4u\r
+\r
+/*\r
+ * RxData bits.\r
+ */\r
+#define RXDATA_OFFSET 0x4u\r
+#define RXDATA_MASK 0xFFu\r
+#define RXDATA_SHIFT 0u\r
+\r
+/*------------------------------------------------------------------------------\r
+ * ControReg1 register details\r
+ */\r
+#define CTRL1_REG_OFFSET 0x8u\r
+\r
+/*\r
+ * Baud value (Lower 8-bits)\r
+ */\r
+#define CTRL1_BAUDVALUE_OFFSET 0x8u\r
+#define CTRL1_BAUDVALUE_MASK 0xFFu\r
+#define CTRL1_BAUDVALUE_SHIFT 0u\r
+\r
+/*------------------------------------------------------------------------------\r
+ * ControReg2 register details\r
+ */\r
+#define CTRL2_REG_OFFSET 0xCu\r
+\r
+/*\r
+ * Bit length\r
+ */\r
+#define CTRL2_BIT_LENGTH_OFFSET 0xCu\r
+#define CTRL2_BIT_LENGTH_MASK 0x01u\r
+#define CTRL2_BIT_LENGTH_SHIFT 0u\r
+\r
+/*\r
+ * Parity enable.\r
+ */\r
+#define CTRL2_PARITY_EN_OFFSET 0xCu\r
+#define CTRL2_PARITY_EN_MASK 0x02u\r
+#define CTRL2_PARITY_EN_SHIFT 1u\r
+\r
+/*\r
+ * Odd/even parity selection.\r
+ */\r
+#define CTRL2_ODD_EVEN_OFFSET 0xCu\r
+#define CTRL2_ODD_EVEN_MASK 0x04u\r
+#define CTRL2_ODD_EVEN_SHIFT 2u\r
+\r
+/*\r
+ * Baud value (Higher 5-bits)\r
+ */\r
+#define CTRL2_BAUDVALUE_OFFSET 0xCu\r
+#define CTRL2_BAUDVALUE_MASK 0xF8u\r
+#define CTRL2_BAUDVALUE_SHIFT 3u\r
+\r
+/*------------------------------------------------------------------------------\r
+ * StatusReg register details\r
+ */\r
+#define StatusReg_REG_OFFSET 0x10u\r
+\r
+#define STATUS_REG_OFFSET 0x10u\r
+\r
+/*\r
+ * Transmit ready.\r
+ */\r
+#define STATUS_TXRDY_OFFSET 0x10u\r
+#define STATUS_TXRDY_MASK 0x01u\r
+#define STATUS_TXRDY_SHIFT 0u\r
+\r
+/*\r
+ * Receive full.\r
+ */\r
+#define STATUS_RXFULL_OFFSET 0x10u\r
+#define STATUS_RXFULL_MASK 0x02u\r
+#define STATUS_RXFULL_SHIFT 1u\r
+\r
+/*\r
+ * Parity error.\r
+ */\r
+#define STATUS_PARITYERR_OFFSET 0x10u\r
+#define STATUS_PARITYERR_MASK 0x04u\r
+#define STATUS_PARITYERR_SHIFT 2u\r
+\r
+/*\r
+ * Overflow.\r
+ */\r
+#define STATUS_OVERFLOW_OFFSET 0x10u\r
+#define STATUS_OVERFLOW_MASK 0x08u\r
+#define STATUS_OVERFLOW_SHIFT 3u\r
+\r
+/*\r
+ * Frame Error.\r
+ */\r
+#define STATUS_FRAMERR_OFFSET 0x10u\r
+#define STATUS_FRAMERR_MASK 0x10u\r
+#define STATUS_FRAMERR_SHIFT 4u\r
+\r
+#ifdef __cplusplus\r
+}\r
+#endif\r
+\r
+#endif /* __CORE_UART_APB_REGISTERS */\r
--- /dev/null
+/*******************************************************************************\r
+ * (c) Copyright 2007-2018 Microsemi SoC Products Group. All rights reserved.\r
+ * \r
+ * SVN $Revision: 9661 $\r
+ * SVN $Date: 2018-01-15 16:13:33 +0530 (Mon, 15 Jan 2018) $\r
+ */\r
+#ifndef __CPU_TYPES_H\r
+#define __CPU_TYPES_H 1\r
+\r
+#include <stdint.h>\r
+\r
+/*------------------------------------------------------------------------------\r
+ */\r
+typedef unsigned int size_t;\r
+\r
+/*------------------------------------------------------------------------------\r
+ * addr_t: address type.\r
+ * Used to specify the address of peripherals present in the processor's memory\r
+ * map.\r
+ */\r
+typedef unsigned int addr_t;\r
+\r
+/*------------------------------------------------------------------------------\r
+ * psr_t: processor state register.\r
+ * Used by HAL_disable_interrupts() and HAL_restore_interrupts() to store the\r
+ * processor's state between disabling and restoring interrupts.\r
+ */\r
+typedef unsigned int psr_t;\r
+\r
+#endif /* __CPU_TYPES_H */\r
+\r
--- /dev/null
+/***************************************************************************//**\r
+ * (c) Copyright 2007-2018 Microsemi SoC Products Group. All rights reserved.\r
+ * \r
+ * Hardware abstraction layer functions.\r
+ * \r
+ * SVN $Revision: 9661 $\r
+ * SVN $Date: 2018-01-15 16:13:33 +0530 (Mon, 15 Jan 2018) $\r
+ */\r
+#ifndef HAL_H_\r
+#define HAL_H_\r
+\r
+#include "cpu_types.h"\r
+#include "hw_reg_access.h"\r
+\r
+/***************************************************************************//**\r
+ * Enable all interrupts at the processor level.\r
+ */\r
+void HAL_enable_interrupts( void );\r
+\r
+/***************************************************************************//**\r
+ * Disable all interrupts at the processor core level.\r
+ * Return the interrupts enable state before disabling occured so that it can \r
+ * later be restored. \r
+ */\r
+psr_t HAL_disable_interrupts( void );\r
+\r
+/***************************************************************************//**\r
+ * Restore the interrupts enable state at the processor core level.\r
+ * This function is normally passed the value returned from a previous call to\r
+ * HAL_disable_interrupts(). \r
+ */\r
+void HAL_restore_interrupts( psr_t saved_psr );\r
+\r
+/***************************************************************************//**\r
+ */\r
+#define FIELD_OFFSET(FIELD_NAME) (FIELD_NAME##_OFFSET)\r
+#define FIELD_SHIFT(FIELD_NAME) (FIELD_NAME##_SHIFT)\r
+#define FIELD_MASK(FIELD_NAME) (FIELD_NAME##_MASK)\r
+\r
+/***************************************************************************//**\r
+ * The macro HAL_set_32bit_reg() allows writing a 32 bits wide register.\r
+ *\r
+ * BASE_ADDR: A variable of type addr_t specifying the base address of the\r
+ * peripheral containing the register.\r
+ * REG_NAME: A string identifying the register to write. These strings are\r
+ * specified in a header file associated with the peripheral.\r
+ * VALUE: A variable of type uint32_t containing the value to write.\r
+ */\r
+#define HAL_set_32bit_reg(BASE_ADDR, REG_NAME, VALUE) \\r
+ (HW_set_32bit_reg( ((BASE_ADDR) + (REG_NAME##_REG_OFFSET)), (VALUE) ))\r
+\r
+/***************************************************************************//**\r
+ * The macro HAL_get_32bit_reg() is used to read the value of a 32 bits wide\r
+ * register.\r
+ * \r
+ * BASE_ADDR: A variable of type addr_t specifying the base address of the\r
+ * peripheral containing the register.\r
+ * REG_NAME: A string identifying the register to read. These strings are\r
+ * specified in a header file associated with the peripheral.\r
+ * RETURN: This function-like macro returns a uint32_t value.\r
+ */\r
+#define HAL_get_32bit_reg(BASE_ADDR, REG_NAME) \\r
+ (HW_get_32bit_reg( ((BASE_ADDR) + (REG_NAME##_REG_OFFSET)) ))\r
+\r
+/***************************************************************************//**\r
+ * The macro HAL_set_32bit_reg_field() is used to write a field within a\r
+ * 32 bits wide register. The field written can be one or more bits.\r
+ * \r
+ * BASE_ADDR: A variable of type addr_t specifying the base address of the\r
+ * peripheral containing the register.\r
+ * FIELD_NAME: A string identifying the register field to write. These strings\r
+ * are specified in a header file associated with the peripheral.\r
+ * VALUE: A variable of type uint32_t containing the field value to write.\r
+ */\r
+#define HAL_set_32bit_reg_field(BASE_ADDR, FIELD_NAME, VALUE) \\r
+ (HW_set_32bit_reg_field(\\r
+ (BASE_ADDR) + FIELD_OFFSET(FIELD_NAME),\\r
+ FIELD_SHIFT(FIELD_NAME),\\r
+ FIELD_MASK(FIELD_NAME),\\r
+ (VALUE)))\r
+ \r
+/***************************************************************************//**\r
+ * The macro HAL_get_32bit_reg_field() is used to read a register field from\r
+ * within a 32 bit wide peripheral register. The field can be one or more bits.\r
+ * \r
+ * BASE_ADDR: A variable of type addr_t specifying the base address of the\r
+ * peripheral containing the register.\r
+ * FIELD_NAME: A string identifying the register field to write. These strings\r
+ * are specified in a header file associated with the peripheral.\r
+ * RETURN: This function-like macro returns a uint32_t value.\r
+ */\r
+#define HAL_get_32bit_reg_field(BASE_ADDR, FIELD_NAME) \\r
+ (HW_get_32bit_reg_field(\\r
+ (BASE_ADDR) + FIELD_OFFSET(FIELD_NAME),\\r
+ FIELD_SHIFT(FIELD_NAME),\\r
+ FIELD_MASK(FIELD_NAME)))\r
+ \r
+/***************************************************************************//**\r
+ * The macro HAL_set_16bit_reg() allows writing a 16 bits wide register.\r
+ *\r
+ * BASE_ADDR: A variable of type addr_t specifying the base address of the\r
+ * peripheral containing the register.\r
+ * REG_NAME: A string identifying the register to write. These strings are\r
+ * specified in a header file associated with the peripheral.\r
+ * VALUE: A variable of type uint_fast16_t containing the value to write.\r
+ */\r
+#define HAL_set_16bit_reg(BASE_ADDR, REG_NAME, VALUE) \\r
+ (HW_set_16bit_reg( ((BASE_ADDR) + (REG_NAME##_REG_OFFSET)), (VALUE) ))\r
+\r
+/***************************************************************************//**\r
+ * The macro HAL_get_16bit_reg() is used to read the value of a 16 bits wide\r
+ * register.\r
+ * \r
+ * BASE_ADDR: A variable of type addr_t specifying the base address of the\r
+ * peripheral containing the register.\r
+ * REG_NAME: A string identifying the register to read. These strings are\r
+ * specified in a header file associated with the peripheral.\r
+ * RETURN: This function-like macro returns a uint16_t value.\r
+ */\r
+#define HAL_get_16bit_reg(BASE_ADDR, REG_NAME) \\r
+ (HW_get_16bit_reg( (BASE_ADDR) + (REG_NAME##_REG_OFFSET) ))\r
+\r
+/***************************************************************************//**\r
+ * The macro HAL_set_16bit_reg_field() is used to write a field within a\r
+ * 16 bits wide register. The field written can be one or more bits.\r
+ * \r
+ * BASE_ADDR: A variable of type addr_t specifying the base address of the\r
+ * peripheral containing the register.\r
+ * FIELD_NAME: A string identifying the register field to write. These strings\r
+ * are specified in a header file associated with the peripheral.\r
+ * VALUE: A variable of type uint16_t containing the field value to write.\r
+ */\r
+#define HAL_set_16bit_reg_field(BASE_ADDR, FIELD_NAME, VALUE) \\r
+ (HW_set_16bit_reg_field(\\r
+ (BASE_ADDR) + FIELD_OFFSET(FIELD_NAME),\\r
+ FIELD_SHIFT(FIELD_NAME),\\r
+ FIELD_MASK(FIELD_NAME),\\r
+ (VALUE))) \r
+\r
+/***************************************************************************//**\r
+ * The macro HAL_get_16bit_reg_field() is used to read a register field from\r
+ * within a 8 bit wide peripheral register. The field can be one or more bits.\r
+ * \r
+ * BASE_ADDR: A variable of type addr_t specifying the base address of the\r
+ * peripheral containing the register.\r
+ * FIELD_NAME: A string identifying the register field to write. These strings\r
+ * are specified in a header file associated with the peripheral.\r
+ * RETURN: This function-like macro returns a uint16_t value.\r
+ */\r
+#define HAL_get_16bit_reg_field(BASE_ADDR, FIELD_NAME) \\r
+ (HW_get_16bit_reg_field(\\r
+ (BASE_ADDR) + FIELD_OFFSET(FIELD_NAME),\\r
+ FIELD_SHIFT(FIELD_NAME),\\r
+ FIELD_MASK(FIELD_NAME)))\r
+\r
+/***************************************************************************//**\r
+ * The macro HAL_set_8bit_reg() allows writing a 8 bits wide register.\r
+ *\r
+ * BASE_ADDR: A variable of type addr_t specifying the base address of the\r
+ * peripheral containing the register.\r
+ * REG_NAME: A string identifying the register to write. These strings are\r
+ * specified in a header file associated with the peripheral.\r
+ * VALUE: A variable of type uint_fast8_t containing the value to write.\r
+ */\r
+#define HAL_set_8bit_reg(BASE_ADDR, REG_NAME, VALUE) \\r
+ (HW_set_8bit_reg( ((BASE_ADDR) + (REG_NAME##_REG_OFFSET)), (VALUE) ))\r
+\r
+/***************************************************************************//**\r
+ * The macro HAL_get_8bit_reg() is used to read the value of a 8 bits wide\r
+ * register.\r
+ * \r
+ * BASE_ADDR: A variable of type addr_t specifying the base address of the\r
+ * peripheral containing the register.\r
+ * REG_NAME: A string identifying the register to read. These strings are\r
+ * specified in a header file associated with the peripheral.\r
+ * RETURN: This function-like macro returns a uint8_t value.\r
+ */\r
+#define HAL_get_8bit_reg(BASE_ADDR, REG_NAME) \\r
+ (HW_get_8bit_reg( (BASE_ADDR) + (REG_NAME##_REG_OFFSET) ))\r
+\r
+/***************************************************************************//**\r
+ */\r
+#define HAL_set_8bit_reg_field(BASE_ADDR, FIELD_NAME, VALUE) \\r
+ (HW_set_8bit_reg_field(\\r
+ (BASE_ADDR) + FIELD_OFFSET(FIELD_NAME),\\r
+ FIELD_SHIFT(FIELD_NAME),\\r
+ FIELD_MASK(FIELD_NAME),\\r
+ (VALUE)))\r
+\r
+/***************************************************************************//**\r
+ * The macro HAL_get_8bit_reg_field() is used to read a register field from\r
+ * within a 8 bit wide peripheral register. The field can be one or more bits.\r
+ * \r
+ * BASE_ADDR: A variable of type addr_t specifying the base address of the\r
+ * peripheral containing the register.\r
+ * FIELD_NAME: A string identifying the register field to write. These strings\r
+ * are specified in a header file associated with the peripheral.\r
+ * RETURN: This function-like macro returns a uint8_t value.\r
+ */\r
+#define HAL_get_8bit_reg_field(BASE_ADDR, FIELD_NAME) \\r
+ (HW_get_8bit_reg_field(\\r
+ (BASE_ADDR) + FIELD_OFFSET(FIELD_NAME),\\r
+ FIELD_SHIFT(FIELD_NAME),\\r
+ FIELD_MASK(FIELD_NAME)))\r
+ \r
+#endif /*HAL_H_*/\r
+\r
--- /dev/null
+/*******************************************************************************\r
+ * (c) Copyright 2008-2018 Microsemi SoC Products Group. All rights reserved.\r
+ * \r
+ * SVN $Revision: 9661 $\r
+ * SVN $Date: 2018-01-15 16:13:33 +0530 (Mon, 15 Jan 2018) $\r
+ */\r
+#ifndef HAL_ASSERT_HEADER\r
+#define HAL_ASSERT_HEADER\r
+\r
+#define NDEBUG 1\r
+\r
+#if defined(NDEBUG)\r
+/***************************************************************************//**\r
+ * HAL_ASSERT() is defined out when the NDEBUG symbol is used.\r
+ ******************************************************************************/\r
+#define HAL_ASSERT(CHECK)\r
+\r
+#else\r
+/***************************************************************************//**\r
+ * Default behaviour for HAL_ASSERT() macro:\r
+ *------------------------------------------------------------------------------\r
+ The behaviour is toolchain specific and project setting specific.\r
+ ******************************************************************************/\r
+#define HAL_ASSERT(CHECK) ASSERT(CHECK);\r
+\r
+#endif /* NDEBUG */\r
+\r
+#endif /* HAL_ASSERT_HEADER */\r
+\r
--- /dev/null
+/***************************************************************************//**\r
+ * (c) Copyright 2007-2018 Microsemi SoC Products Group. All rights reserved.\r
+ * \r
+ * Legacy interrupt control functions for the Microsemi driver library hardware\r
+ * abstraction layer.\r
+ *\r
+ * SVN $Revision: 9661 $\r
+ * SVN $Date: 2018-01-15 16:13:33 +0530 (Mon, 15 Jan 2018) $\r
+ */\r
+#include "hal.h"\r
+#include "riscv_hal.h"\r
+\r
+/*------------------------------------------------------------------------------\r
+ * \r
+ */\r
+void HAL_enable_interrupts(void) {\r
+ __enable_irq();\r
+}\r
+\r
+/*------------------------------------------------------------------------------\r
+ * \r
+ */\r
+psr_t HAL_disable_interrupts(void) {\r
+ psr_t psr;\r
+ psr = read_csr(mstatus);\r
+ __disable_irq();\r
+ return(psr);\r
+}\r
+\r
+/*------------------------------------------------------------------------------\r
+ * \r
+ */\r
+void HAL_restore_interrupts(psr_t saved_psr) {\r
+ write_csr(mstatus, saved_psr);\r
+}\r
+\r
--- /dev/null
+/*******************************************************************************\r
+ * (c) Copyright 2007-2018 Microsemi SoC Products Group. All rights reserved.\r
+ * \r
+ * Hardware registers access macros.\r
+ * \r
+ * THE MACROS DEFINED IN THIS FILE ARE DEPRECATED. DO NOT USED FOR NEW \r
+ * DEVELOPMENT.\r
+ *\r
+ * These macros are used to access peripheral's registers. They allow access to\r
+ * 8, 16 and 32 bit wide registers. All accesses to peripheral registers should\r
+ * be done through these macros in order to ease porting across different \r
+ * processors/bus architectures.\r
+ * \r
+ * Some of these macros also allow to access a specific register field.\r
+ * \r
+ * SVN $Revision: 9661 $\r
+ * SVN $Date: 2018-01-15 16:13:33 +0530 (Mon, 15 Jan 2018) $\r
+ */\r
+#ifndef __HW_REGISTER_MACROS_H\r
+#define __HW_REGISTER_MACROS_H 1\r
+\r
+/*------------------------------------------------------------------------------\r
+ * 32 bits registers access:\r
+ */\r
+#define HW_get_uint32_reg(BASE_ADDR, REG_OFFSET) (*((uint32_t volatile *)(BASE_ADDR + REG_OFFSET##_REG_OFFSET)))\r
+\r
+#define HW_set_uint32_reg(BASE_ADDR, REG_OFFSET, VALUE) (*((uint32_t volatile *)(BASE_ADDR + REG_OFFSET##_REG_OFFSET)) = (VALUE))\r
+\r
+#define HW_set_uint32_reg_field(BASE_ADDR, FIELD, VALUE) \\r
+ (*((uint32_t volatile *)(BASE_ADDR + FIELD##_OFFSET)) = \\r
+ ( \\r
+ (uint32_t) \\r
+ ( \\r
+ (*((uint32_t volatile *)(BASE_ADDR + FIELD##_OFFSET))) & ~FIELD##_MASK) | \\r
+ (uint32_t)(((VALUE) << FIELD##_SHIFT) & FIELD##_MASK) \\r
+ ) \\r
+ )\r
+\r
+#define HW_get_uint32_reg_field( BASE_ADDR, FIELD ) \\r
+ (( (*((uint32_t volatile *)(BASE_ADDR + FIELD##_OFFSET))) & FIELD##_MASK) >> FIELD##_SHIFT)\r
+\r
+/*------------------------------------------------------------------------------\r
+ * 32 bits memory access:\r
+ */\r
+#define HW_get_uint32(BASE_ADDR) (*((uint32_t volatile *)(BASE_ADDR)))\r
+\r
+#define HW_set_uint32(BASE_ADDR, VALUE) (*((uint32_t volatile *)(BASE_ADDR)) = (VALUE))\r
+\r
+/*------------------------------------------------------------------------------\r
+ * 16 bits registers access:\r
+ */\r
+#define HW_get_uint16_reg(BASE_ADDR, REG_OFFSET) (*((uint16_t volatile *)(BASE_ADDR + REG_OFFSET##_REG_OFFSET)))\r
+\r
+#define HW_set_uint16_reg(BASE_ADDR, REG_OFFSET, VALUE) (*((uint16_t volatile *)(BASE_ADDR + REG_OFFSET##_REG_OFFSET)) = (VALUE))\r
+\r
+#define HW_set_uint16_reg_field(BASE_ADDR, FIELD, VALUE) \\r
+ (*((uint16_t volatile *)(BASE_ADDR + FIELD##_OFFSET)) = \\r
+ ( \\r
+ (uint16_t) \\r
+ ( \\r
+ (*((uint16_t volatile *)(BASE_ADDR + FIELD##_OFFSET))) & ~FIELD##_MASK) | \\r
+ (uint16_t)(((VALUE) << FIELD##_SHIFT) & FIELD##_MASK) \\r
+ ) \\r
+ )\r
+\r
+#define HW_get_uint16_reg_field( BASE_ADDR, FIELD ) \\r
+ (( (*((uint16_t volatile *)(BASE_ADDR + FIELD##_OFFSET))) & FIELD##_MASK) >> FIELD##_SHIFT)\r
+\r
+/*------------------------------------------------------------------------------\r
+ * 8 bits registers access:\r
+ */\r
+#define HW_get_uint8_reg(BASE_ADDR, REG_OFFSET) (*((uint8_t volatile *)(BASE_ADDR + REG_OFFSET##_REG_OFFSET)))\r
+\r
+#define HW_set_uint8_reg(BASE_ADDR, REG_OFFSET, VALUE) (*((uint8_t volatile *)(BASE_ADDR + REG_OFFSET##_REG_OFFSET)) = (VALUE))\r
+ \r
+#define HW_set_uint8_reg_field(BASE_ADDR, FIELD, VALUE) \\r
+ (*((uint8_t volatile *)(BASE_ADDR + FIELD##_OFFSET)) = \\r
+ ( \\r
+ (uint8_t) \\r
+ ( \\r
+ (*((uint8_t volatile *)(BASE_ADDR + FIELD##_OFFSET))) & ~FIELD##_MASK) | \\r
+ (uint8_t)(((VALUE) << FIELD##_SHIFT) & FIELD##_MASK) \\r
+ ) \\r
+ )\r
+\r
+#define HW_get_uint8_reg_field( BASE_ADDR, FIELD ) \\r
+ (( (*((uint8_t volatile *)(BASE_ADDR + FIELD##_OFFSET))) & FIELD##_MASK) >> FIELD##_SHIFT)\r
+\r
+/*------------------------------------------------------------------------------\r
+ * 8 bits memory access:\r
+ */\r
+#define HW_get_uint8(BASE_ADDR) (*((uint8_t volatile *)(BASE_ADDR)))\r
+\r
+#define HW_set_uint8(BASE_ADDR, VALUE) (*((uint8_t volatile *)(BASE_ADDR)) = (VALUE))\r
+ \r
+#endif /* __HW_REGISTER_MACROS_H */\r
+\r
--- /dev/null
+/***************************************************************************//**\r
+ * (c) Copyright 2007-2018 Microsemi SoC Products Group. All rights reserved.\r
+ *\r
+ * Hardware registers access functions.\r
+ * The implementation of these function is platform and toolchain specific.\r
+ * The functions declared here are implemented using assembler as part of the\r
+ * processor/toolchain specific HAL.\r
+ *\r
+ * SVN $Revision: 9661 $\r
+ * SVN $Date: 2018-01-15 16:13:33 +0530 (Mon, 15 Jan 2018) $\r
+ */\r
+\r
+.section .text\r
+ .globl HW_set_32bit_reg\r
+ .globl HW_get_32bit_reg\r
+ .globl HW_set_32bit_reg_field\r
+ .globl HW_get_32bit_reg_field\r
+ .globl HW_set_16bit_reg\r
+ .globl HW_get_16bit_reg\r
+ .globl HW_set_16bit_reg_field\r
+ .globl HW_get_16bit_reg_field\r
+ .globl HW_set_8bit_reg\r
+ .globl HW_get_8bit_reg\r
+ .globl HW_set_8bit_reg_field\r
+ .globl HW_get_8bit_reg_field\r
+\r
+\r
+/***************************************************************************//**\r
+ * HW_set_32bit_reg is used to write the content of a 32 bits wide peripheral\r
+ * register.\r
+ *\r
+ * a0: addr_t reg_addr\r
+ * a1: uint32_t value\r
+ */\r
+HW_set_32bit_reg:\r
+ sw a1, 0(a0)\r
+ ret\r
+\r
+/***************************************************************************//**\r
+ * HW_get_32bit_reg is used to read the content of a 32 bits wide peripheral\r
+ * register.\r
+ *\r
+ * R0: addr_t reg_addr\r
+ * @return 32 bits value read from the peripheral register.\r
+ */\r
+HW_get_32bit_reg:\r
+ lw a0, 0(a0)\r
+ ret\r
+\r
+/***************************************************************************//**\r
+ * HW_set_32bit_reg_field is used to set the content of a field in a 32 bits\r
+ * wide peripheral register.\r
+ *\r
+ * a0: addr_t reg_addr\r
+ * a1: int_fast8_t shift\r
+ * a2: uint32_t mask\r
+ * a3: uint32_t value\r
+ */\r
+HW_set_32bit_reg_field:\r
+ mv t3, a3\r
+ sll t3, t3, a1\r
+ and t3, t3, a2\r
+ lw t1, 0(a0)\r
+ mv t2, a2\r
+ not t2, t2\r
+ and t1, t1, t2\r
+ or t1, t1, t3\r
+ sw t1, 0(a0)\r
+ ret\r
+\r
+/***************************************************************************//**\r
+ * HW_get_32bit_reg_field is used to read the content of a field out of a\r
+ * 32 bits wide peripheral register.\r
+ *\r
+ * a0: addr_t reg_addr\r
+ * a1: int_fast8_t shift\r
+ * a2: uint32_t mask\r
+ *\r
+ * @return 32 bits value containing the register field value specified\r
+ * as parameter.\r
+ */\r
+HW_get_32bit_reg_field:\r
+ lw a0, 0(a0)\r
+ and a0, a0, a2\r
+ srl a0, a0, a1\r
+ ret\r
+\r
+/***************************************************************************//**\r
+ * HW_set_16bit_reg is used to write the content of a 16 bits wide peripheral\r
+ * register.\r
+ *\r
+ * a0: addr_t reg_addr\r
+ * a1: uint_fast16_t value\r
+ */\r
+HW_set_16bit_reg:\r
+ sh a1, 0(a0)\r
+ ret\r
+\r
+/***************************************************************************//**\r
+ * HW_get_16bit_reg is used to read the content of a 16 bits wide peripheral\r
+ * register.\r
+ *\r
+ * a0: addr_t reg_addr\r
+ * @return 16 bits value read from the peripheral register.\r
+ */\r
+HW_get_16bit_reg:\r
+ lh a0, (a0)\r
+ ret\r
+\r
+/***************************************************************************//**\r
+ * HW_set_16bit_reg_field is used to set the content of a field in a 16 bits\r
+ * wide peripheral register.\r
+ *\r
+ * a0: addr_t reg_addr\r
+ * a1: int_fast8_t shift\r
+ * a2: uint_fast16_t mask\r
+ * a3: uint_fast16_t value\r
+ * @param value Value to be written in the specified field.\r
+ */\r
+HW_set_16bit_reg_field:\r
+ mv t3, a3\r
+ sll t3, t3, a1\r
+ and t3, t3, a2\r
+ lh t1, 0(a0)\r
+ mv t2, a2\r
+ not t2, t2\r
+ and t1, t1, t2\r
+ or t1, t1, t3\r
+ sh t1, 0(a0)\r
+ ret\r
+\r
+/***************************************************************************//**\r
+ * HW_get_16bit_reg_field is used to read the content of a field from a\r
+ * 16 bits wide peripheral register.\r
+ *\r
+ * a0: addr_t reg_addr\r
+ * a1: int_fast8_t shift\r
+ * a2: uint_fast16_t mask\r
+ *\r
+ * @return 16 bits value containing the register field value specified\r
+ * as parameter.\r
+ */\r
+HW_get_16bit_reg_field:\r
+ lh a0, 0(a0)\r
+ and a0, a0, a2\r
+ srl a0, a0, a1\r
+ ret\r
+\r
+/***************************************************************************//**\r
+ * HW_set_8bit_reg is used to write the content of a 8 bits wide peripheral\r
+ * register.\r
+ *\r
+ * a0: addr_t reg_addr\r
+ * a1: uint_fast8_t value\r
+ */\r
+HW_set_8bit_reg:\r
+ sb a1, 0(a0)\r
+ ret\r
+\r
+/***************************************************************************//**\r
+ * HW_get_8bit_reg is used to read the content of a 8 bits wide peripheral\r
+ * register.\r
+ *\r
+ * a0: addr_t reg_addr\r
+ * @return 8 bits value read from the peripheral register.\r
+ */\r
+HW_get_8bit_reg:\r
+ lb a0, 0(a0)\r
+ ret\r
+\r
+/***************************************************************************//**\r
+ * HW_set_8bit_reg_field is used to set the content of a field in a 8 bits\r
+ * wide peripheral register.\r
+ *\r
+ * a0: addr_t reg_addr,\r
+ * a1: int_fast8_t shift\r
+ * a2: uint_fast8_t mask\r
+ * a3: uint_fast8_t value\r
+ */\r
+HW_set_8bit_reg_field:\r
+ mv t3, a3\r
+ sll t3, t3, a1\r
+ and t3, t3, a2\r
+ lb t1, 0(a0)\r
+ mv t2, a2\r
+ not t2, t2\r
+ and t1, t1, t2\r
+ or t1, t1, t3\r
+ sb t1, 0(a0)\r
+ ret\r
+\r
+/***************************************************************************//**\r
+ * HW_get_8bit_reg_field is used to read the content of a field from a\r
+ * 8 bits wide peripheral register.\r
+ *\r
+ * a0: addr_t reg_addr\r
+ * a1: int_fast8_t shift\r
+ * a2: uint_fast8_t mask\r
+ *\r
+ * @return 8 bits value containing the register field value specified\r
+ * as parameter.\r
+ */\r
+HW_get_8bit_reg_field:\r
+ lb a0, 0(a0)\r
+ and a0, a0, a2\r
+ srl a0, a0, a1\r
+ ret\r
+\r
+.end\r
--- /dev/null
+/***************************************************************************//**\r
+ * (c) Copyright 2007-2018 Microsemi SoC Products Group. All rights reserved.\r
+ * \r
+ * Hardware registers access functions.\r
+ * The implementation of these function is platform and toolchain specific.\r
+ * The functions declared here are implemented using assembler as part of the \r
+ * processor/toolchain specific HAL.\r
+ * \r
+ * SVN $Revision: 9661 $\r
+ * SVN $Date: 2018-01-15 16:13:33 +0530 (Mon, 15 Jan 2018) $\r
+ */\r
+#ifndef HW_REG_ACCESS\r
+#define HW_REG_ACCESS\r
+\r
+#include "cpu_types.h"\r
+/***************************************************************************//**\r
+ * HW_set_32bit_reg is used to write the content of a 32 bits wide peripheral\r
+ * register.\r
+ * \r
+ * @param reg_addr Address in the processor's memory map of the register to\r
+ * write.\r
+ * @param value Value to be written into the peripheral register.\r
+ */\r
+void\r
+HW_set_32bit_reg\r
+(\r
+ addr_t reg_addr,\r
+ uint32_t value\r
+);\r
+\r
+/***************************************************************************//**\r
+ * HW_get_32bit_reg is used to read the content of a 32 bits wide peripheral\r
+ * register.\r
+ * \r
+ * @param reg_addr Address in the processor's memory map of the register to\r
+ * read.\r
+ * @return 32 bits value read from the peripheral register.\r
+ */\r
+uint32_t\r
+HW_get_32bit_reg\r
+(\r
+ addr_t reg_addr\r
+);\r
+\r
+/***************************************************************************//**\r
+ * HW_set_32bit_reg_field is used to set the content of a field in a 32 bits \r
+ * wide peripheral register.\r
+ * \r
+ * @param reg_addr Address in the processor's memory map of the register to\r
+ * be written.\r
+ * @param shift Bit offset of the register field to be read within the \r
+ * register.\r
+ * @param mask Bit mask to be applied to the raw register value to filter\r
+ * out the other register fields values.\r
+ * @param value Value to be written in the specified field.\r
+ */\r
+void\r
+HW_set_32bit_reg_field\r
+(\r
+ addr_t reg_addr,\r
+ int_fast8_t shift,\r
+ uint32_t mask,\r
+ uint32_t value\r
+);\r
+\r
+/***************************************************************************//**\r
+ * HW_get_32bit_reg_field is used to read the content of a field out of a \r
+ * 32 bits wide peripheral register.\r
+ * \r
+ * @param reg_addr Address in the processor's memory map of the register to\r
+ * read.\r
+ * @param shift Bit offset of the register field to be written within the \r
+ * register.\r
+ * @param mask Bit mask to be applied to the raw register value to filter\r
+ * out the other register fields values.\r
+ *\r
+ * @return 32 bits value containing the register field value specified\r
+ * as parameter.\r
+ */\r
+uint32_t \r
+HW_get_32bit_reg_field\r
+(\r
+ addr_t reg_addr,\r
+ int_fast8_t shift,\r
+ uint32_t mask\r
+);\r
+\r
+/***************************************************************************//**\r
+ * HW_set_16bit_reg is used to write the content of a 16 bits wide peripheral\r
+ * register.\r
+ * \r
+ * @param reg_addr Address in the processor's memory map of the register to\r
+ * write.\r
+ * @param value Value to be written into the peripheral register.\r
+ */\r
+void\r
+HW_set_16bit_reg\r
+(\r
+ addr_t reg_addr,\r
+ uint_fast16_t value\r
+);\r
+\r
+/***************************************************************************//**\r
+ * HW_get_16bit_reg is used to read the content of a 16 bits wide peripheral\r
+ * register.\r
+ * \r
+ * @param reg_addr Address in the processor's memory map of the register to\r
+ * read.\r
+ * @return 16 bits value read from the peripheral register.\r
+ */\r
+uint16_t\r
+HW_get_16bit_reg\r
+(\r
+ addr_t reg_addr\r
+);\r
+\r
+/***************************************************************************//**\r
+ * HW_set_16bit_reg_field is used to set the content of a field in a 16 bits \r
+ * wide peripheral register.\r
+ * \r
+ * @param reg_addr Address in the processor's memory map of the register to\r
+ * be written.\r
+ * @param shift Bit offset of the register field to be read within the \r
+ * register.\r
+ * @param mask Bit mask to be applied to the raw register value to filter\r
+ * out the other register fields values.\r
+ * @param value Value to be written in the specified field.\r
+ */\r
+void HW_set_16bit_reg_field\r
+(\r
+ addr_t reg_addr,\r
+ int_fast8_t shift,\r
+ uint_fast16_t mask,\r
+ uint_fast16_t value\r
+);\r
+\r
+/***************************************************************************//**\r
+ * HW_get_16bit_reg_field is used to read the content of a field from a \r
+ * 16 bits wide peripheral register.\r
+ * \r
+ * @param reg_addr Address in the processor's memory map of the register to\r
+ * read.\r
+ * @param shift Bit offset of the register field to be written within the \r
+ * register.\r
+ * @param mask Bit mask to be applied to the raw register value to filter\r
+ * out the other register fields values.\r
+ *\r
+ * @return 16 bits value containing the register field value specified\r
+ * as parameter.\r
+ */\r
+uint16_t HW_get_16bit_reg_field\r
+(\r
+ addr_t reg_addr,\r
+ int_fast8_t shift,\r
+ uint_fast16_t mask\r
+);\r
+\r
+/***************************************************************************//**\r
+ * HW_set_8bit_reg is used to write the content of a 8 bits wide peripheral\r
+ * register.\r
+ * \r
+ * @param reg_addr Address in the processor's memory map of the register to\r
+ * write.\r
+ * @param value Value to be written into the peripheral register.\r
+ */\r
+void\r
+HW_set_8bit_reg\r
+(\r
+ addr_t reg_addr,\r
+ uint_fast8_t value\r
+);\r
+\r
+/***************************************************************************//**\r
+ * HW_get_8bit_reg is used to read the content of a 8 bits wide peripheral\r
+ * register.\r
+ * \r
+ * @param reg_addr Address in the processor's memory map of the register to\r
+ * read.\r
+ * @return 8 bits value read from the peripheral register.\r
+ */\r
+uint8_t\r
+HW_get_8bit_reg\r
+(\r
+ addr_t reg_addr\r
+);\r
+\r
+/***************************************************************************//**\r
+ * HW_set_8bit_reg_field is used to set the content of a field in a 8 bits \r
+ * wide peripheral register.\r
+ * \r
+ * @param reg_addr Address in the processor's memory map of the register to\r
+ * be written.\r
+ * @param shift Bit offset of the register field to be read within the \r
+ * register.\r
+ * @param mask Bit mask to be applied to the raw register value to filter\r
+ * out the other register fields values.\r
+ * @param value Value to be written in the specified field.\r
+ */\r
+void HW_set_8bit_reg_field\r
+(\r
+ addr_t reg_addr,\r
+ int_fast8_t shift,\r
+ uint_fast8_t mask,\r
+ uint_fast8_t value\r
+);\r
+\r
+/***************************************************************************//**\r
+ * HW_get_8bit_reg_field is used to read the content of a field from a \r
+ * 8 bits wide peripheral register.\r
+ * \r
+ * @param reg_addr Address in the processor's memory map of the register to\r
+ * read.\r
+ * @param shift Bit offset of the register field to be written within the \r
+ * register.\r
+ * @param mask Bit mask to be applied to the raw register value to filter\r
+ * out the other register fields values.\r
+ *\r
+ * @return 8 bits value containing the register field value specified\r
+ * as parameter.\r
+ */\r
+uint8_t HW_get_8bit_reg_field\r
+(\r
+ addr_t reg_addr,\r
+ int_fast8_t shift,\r
+ uint_fast8_t mask\r
+);\r
+\r
+#endif /* HW_REG_ACCESS */\r
+\r
--- /dev/null
+/*******************************************************************************\r
+ * (c) Copyright 2016-2017 Microsemi Corporation. All rights reserved.\r
+ *\r
+ * Platform definitions\r
+ * Version based on requirements of RISCV-HAL\r
+ *\r
+ * SVN $Revision: 9587 $\r
+ * SVN $Date: 2017-11-16 12:53:31 +0530 (Thu, 16 Nov 2017) $\r
+ */\r
+ /*=========================================================================*//**\r
+ @mainpage Sample file detailing how hw_platform.h should be constructed for \r
+ the Mi-V processors.\r
+\r
+ @section intro_sec Introduction\r
+ The hw_platform.h is to be located in the project root directory.\r
+ Currently this file must be hand crafted when using the Mi-V Soft Processor.\r
+ \r
+ You can use this file as sample.\r
+ Rename this file from sample_hw_platform.h to hw_platform.h and store it in\r
+ the root folder of your project. Then customize it per your HW design.\r
+\r
+ @section driver_configuration Project configuration Instructions\r
+ 1. Change SYS_CLK_FREQ define to frequency of Mi-V Soft processor clock\r
+ 2 Add all other core BASE addresses\r
+ 3. Add peripheral Core Interrupt to Mi-V Soft processor interrupt mappings\r
+ 4. Define MSCC_STDIO_UART_BASE_ADDR if you want a CoreUARTapb mapped to STDIO\r
+*//*=========================================================================*/\r
+\r
+#ifndef HW_PLATFORM_H\r
+#define HW_PLATFORM_H\r
+\r
+/***************************************************************************//**\r
+ * Soft-processor clock definition\r
+ * This is the only clock brought over from the Mi-V Soft processor Libero design.\r
+ */\r
+#ifndef SYS_CLK_FREQ\r
+#define SYS_CLK_FREQ 83000000UL\r
+#endif\r
+\r
+/***************************************************************************//**\r
+ * Non-memory Peripheral base addresses\r
+ * Format of define is:\r
+ * <corename>_<instance>_BASE_ADDR\r
+ */\r
+#define COREUARTAPB0_BASE_ADDR 0x70001000UL\r
+#define COREGPIO_IN_BASE_ADDR 0x70002000UL\r
+#define CORETIMER0_BASE_ADDR 0x70003000UL\r
+#define CORETIMER1_BASE_ADDR 0x70004000UL\r
+#define COREGPIO_OUT_BASE_ADDR 0x70005000UL\r
+#define FLASH_CORE_SPI_BASE 0x70006000UL\r
+#define CORE16550_BASE_ADDR 0x70007000UL\r
+\r
+/***************************************************************************//**\r
+ * Peripheral Interrupts are mapped to the corresponding Mi-V Soft processor\r
+ * interrupt from the Libero design.\r
+ * There can be up to 31 external interrupts (IRQ[30:0] pins) on the Mi-V Soft\r
+ * processor.The Mi-V Soft processor external interrupts are defined in the\r
+ * riscv_plic.h\r
+ * These are of the form\r
+ * typedef enum\r
+{\r
+ NoInterrupt_IRQn = 0,\r
+ External_1_IRQn = 1,\r
+ External_2_IRQn = 2,\r
+ .\r
+ .\r
+ .\r
+ External_31_IRQn = 31\r
+} IRQn_Type;\r
+ \r
+ The interrupt 0 on RISC-V processor is not used. The pin IRQ[0] should map to\r
+ External_1_IRQn likewise IRQ[30] should map to External_31_IRQn\r
+ * Format of define is:\r
+ * <corename>_<instance>_<core interrupt name>\r
+ */\r
+\r
+#define TIMER0_IRQn External_30_IRQn\r
+#define TIMER1_IRQn External_31_IRQn\r
+\r
+/****************************************************************************\r
+ * Baud value to achieve a 115200 baud rate with a 83MHz system clock.\r
+ * This value is calculated using the following equation:\r
+ * BAUD_VALUE = (CLOCK / (16 * BAUD_RATE)) - 1\r
+ *****************************************************************************/\r
+#define BAUD_VALUE_115200 (SYS_CLK_FREQ / (16 * 115200)) - 1\r
+\r
+/***************************************************************************//**\r
+ * User edit section- Edit sections below if required\r
+ */\r
+#ifdef MSCC_STDIO_THRU_CORE_UART_APB\r
+/*\r
+ * A base address mapping for the STDIO printf/scanf mapping to CortUARTapb\r
+ * must be provided if it is being used\r
+ *\r
+ * e.g. #define MSCC_STDIO_UART_BASE_ADDR COREUARTAPB1_BASE_ADDR\r
+ */\r
+#define MSCC_STDIO_UART_BASE_ADDR COREUARTAPB0_BASE_ADDR\r
+\r
+#ifndef MSCC_STDIO_UART_BASE_ADDR\r
+#error MSCC_STDIO_UART_BASE_ADDR not defined- e.g. #define MSCC_STDIO_UART_BASE_ADDR COREUARTAPB1_BASE_ADDR\r
+#endif\r
+\r
+#ifndef MSCC_STDIO_BAUD_VALUE\r
+/*\r
+ * The MSCC_STDIO_BAUD_VALUE define should be set in your project's settings to\r
+ * specify the baud value used by the standard output CoreUARTapb instance for\r
+ * generating the UART's baud rate if you want a different baud rate from the\r
+ * default of 115200 baud\r
+ */\r
+#define MSCC_STDIO_BAUD_VALUE 115200\r
+#endif /*MSCC_STDIO_BAUD_VALUE*/\r
+\r
+#endif /* end of MSCC_STDIO_THRU_CORE_UART_APB */\r
+/*******************************************************************************\r
+ * End of user edit section\r
+ */\r
+#endif /* HW_PLATFORM_H */\r
+\r
+\r
--- /dev/null
+#include "FreeRTOS.h"\r
+#include "task.h"\r
+#include "queue.h"\r
+#include "timers.h"\r
+\r
+#include "hw_platform.h"\r
+#include "core_uart_apb.h"\r
+#include "task.h"\r
+\r
+const char * g_hello_msg = "\r\nFreeRTOS Example\r\n";\r
+\r
+\r
+/* A block time of zero simply means "don't block". */\r
+#define mainDONT_BLOCK ( 0UL )\r
+\r
+/******************************************************************************\r
+ * CoreUARTapb instance data.\r
+ *****************************************************************************/\r
+UART_instance_t g_uart;\r
+/*-----------------------------------------------------------*/\r
+\r
+static void vUartTestTask1( void *pvParameters );\r
+static void vUartTestTask2( void *pvParameters );\r
+\r
+/*\r
+ * FreeRTOS hook for when malloc fails, enable in FreeRTOSConfig.\r
+ */\r
+void vApplicationMallocFailedHook( void );\r
+\r
+/*\r
+ * FreeRTOS hook for when FreeRtos is idling, enable in FreeRTOSConfig.\r
+ */\r
+void vApplicationIdleHook( void );\r
+\r
+/*\r
+ * FreeRTOS hook for when a stack overflow occurs, enable in FreeRTOSConfig.\r
+ */\r
+void vApplicationStackOverflowHook( TaskHandle_t pxTask, char *pcTaskName );\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+int main( void )\r
+{\r
+ PLIC_init();\r
+\r
+ /**************************************************************************\r
+ * Initialize CoreUART with its base address, baud value, and line\r
+ * configuration.\r
+ *************************************************************************/\r
+ UART_init(&g_uart, COREUARTAPB0_BASE_ADDR, BAUD_VALUE_115200,\r
+ (DATA_8_BITS | NO_PARITY) );\r
+\r
+ UART_polled_tx_string( &g_uart, (const uint8_t *)"\r\n\r\n Sample Demonstration of FreeRTOS port for Mi-V processor.\r\n\r\n" );\r
+ UART_polled_tx_string( &g_uart, (const uint8_t *)" This project creates two tasks and runs them at regular intervals.\r\n" );\r
+\r
+ /* Create the two test tasks. */\r
+ xTaskCreate( vUartTestTask1, "UArt1", 1000, NULL, uartPRIMARY_PRIORITY, NULL );\r
+ xTaskCreate( vUartTestTask2, "UArt2", 1000, NULL, uartPRIMARY_PRIORITY, NULL );\r
+\r
+ /* Start the kernel. From here on, only tasks and interrupts will run. */\r
+ vTaskStartScheduler();\r
+\r
+ /* Exit FreeRTOS */\r
+ return 0;\r
+}\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+void vApplicationMallocFailedHook( void )\r
+{\r
+ /* vApplicationMallocFailedHook() will only be called if\r
+ configUSE_MALLOC_FAILED_HOOK is set to 1 in FreeRTOSConfig.h. It is a hook\r
+ function that will get called if a call to pvPortMalloc() fails.\r
+ pvPortMalloc() is called internally by the kernel whenever a task, queue,\r
+ timer or semaphore is created. It is also called by various parts of the\r
+ demo application. If heap_1.c or heap_2.c are used, then the size of the\r
+ heap available to pvPortMalloc() is defined by configTOTAL_HEAP_SIZE in\r
+ FreeRTOSConfig.h, and the xPortGetFreeHeapSize() API function can be used\r
+ to query the size of free heap space that remains (although it does not\r
+ provide information on how the remaining heap might be fragmented). */\r
+ taskDISABLE_INTERRUPTS();\r
+ for( ;; );\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+void vApplicationIdleHook( void )\r
+{\r
+ /* vApplicationIdleHook() will only be called if configUSE_IDLE_HOOK is set\r
+ to 1 in FreeRTOSConfig.h. It will be called on each iteration of the idle\r
+ task. It is essential that code added to this hook function never attempts\r
+ to block in any way (for example, call xQueueReceive() with a block time\r
+ specified, or call vTaskDelay()). If the application makes use of the\r
+ vTaskDelete() API function (as this demo application does) then it is also\r
+ important that vApplicationIdleHook() is permitted to return to its calling\r
+ function, because it is the responsibility of the idle task to clean up\r
+ memory allocated by the kernel to any task that has since been deleted. */\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+void vApplicationStackOverflowHook( TaskHandle_t pxTask, char *pcTaskName )\r
+{\r
+ ( void ) pcTaskName;\r
+ ( void ) pxTask;\r
+\r
+ /* Run time stack overflow checking is performed if\r
+ configCHECK_FOR_STACK_OVERFLOW is defined to 1 or 2. This hook\r
+ function is called if a stack overflow is detected. */\r
+ taskDISABLE_INTERRUPTS();\r
+ for( ;; );\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void vUartTestTask1( void *pvParameters )\r
+{\r
+ ( void ) pvParameters;\r
+\r
+ for( ;; )\r
+ {\r
+ UART_polled_tx_string( &g_uart, (const uint8_t *)"Task - 1\r\n" );\r
+ vTaskDelay(10);\r
+ }\r
+}\r
+\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+static void vUartTestTask2( void *pvParameters )\r
+{\r
+ ( void ) pvParameters;\r
+\r
+ for( ;; )\r
+ {\r
+ UART_polled_tx_string( &g_uart, (const uint8_t *)"Task - 2\r\n" );\r
+ vTaskDelay(5);\r
+ }\r
+}\r
--- /dev/null
+/*******************************************************************************\r
+ * (c) Copyright 2016-2018 Microsemi SoC Products Group. All rights reserved.\r
+ *\r
+ * @file encodings.h\r
+ * @author Microsemi SoC Products Group\r
+ * @brief Mi-V soft processor register bit mask and shift constants encodings.\r
+ *\r
+ * SVN $Revision: 9825 $\r
+ * SVN $Date: 2018-03-19 10:31:41 +0530 (Mon, 19 Mar 2018) $\r
+ */\r
+#ifndef RISCV_CSR_ENCODING_H\r
+#define RISCV_CSR_ENCODING_H\r
+\r
+#ifdef __cplusplus\r
+extern "C" {\r
+#endif\r
+\r
+#define MSTATUS_UIE 0x00000001\r
+#define MSTATUS_SIE 0x00000002\r
+#define MSTATUS_HIE 0x00000004\r
+#define MSTATUS_MIE 0x00000008\r
+#define MSTATUS_UPIE 0x00000010\r
+#define MSTATUS_SPIE 0x00000020\r
+#define MSTATUS_HPIE 0x00000040\r
+#define MSTATUS_MPIE 0x00000080\r
+#define MSTATUS_SPP 0x00000100\r
+#define MSTATUS_HPP 0x00000600\r
+#define MSTATUS_MPP 0x00001800\r
+#define MSTATUS_FS 0x00006000\r
+#define MSTATUS_XS 0x00018000\r
+#define MSTATUS_MPRV 0x00020000\r
+#define MSTATUS_SUM 0x00040000 /*changed in v1.10*/\r
+#define MSTATUS_MXR 0x00080000 /*changed in v1.10*/\r
+#define MSTATUS_TVM 0x00100000 /*changed in v1.10*/\r
+#define MSTATUS_TW 0x00200000 /*changed in v1.10*/\r
+#define MSTATUS_TSR 0x00400000 /*changed in v1.10*/\r
+#define MSTATUS_RES 0x7F800000 /*changed in v1.10*/\r
+#define MSTATUS32_SD 0x80000000\r
+#define MSTATUS64_SD 0x8000000000000000\r
+\r
+#define MCAUSE32_CAUSE 0x7FFFFFFF\r
+#define MCAUSE64_CAUSE 0x7FFFFFFFFFFFFFFF\r
+#define MCAUSE32_INT 0x80000000\r
+#define MCAUSE64_INT 0x8000000000000000\r
+\r
+#define SSTATUS_UIE 0x00000001\r
+#define SSTATUS_SIE 0x00000002\r
+#define SSTATUS_UPIE 0x00000010\r
+#define SSTATUS_SPIE 0x00000020\r
+#define SSTATUS_SPP 0x00000100\r
+#define SSTATUS_FS 0x00006000\r
+#define SSTATUS_XS 0x00018000\r
+#define SSTATUS_PUM 0x00040000\r
+#define SSTATUS32_SD 0x80000000\r
+#define SSTATUS64_SD 0x8000000000000000\r
+\r
+#define MIP_SSIP (1u << IRQ_S_SOFT)\r
+#define MIP_HSIP (1u << IRQ_H_SOFT)\r
+#define MIP_MSIP (1u << IRQ_M_SOFT)\r
+#define MIP_STIP (1u << IRQ_S_TIMER)\r
+#define MIP_HTIP (1u << IRQ_H_TIMER)\r
+#define MIP_MTIP (1u << IRQ_M_TIMER)\r
+#define MIP_SEIP (1u << IRQ_S_EXT)\r
+#define MIP_HEIP (1u << IRQ_H_EXT)\r
+#define MIP_MEIP (1u << IRQ_M_EXT)\r
+\r
+#define SIP_SSIP MIP_SSIP\r
+#define SIP_STIP MIP_STIP\r
+\r
+#define PRV_U 0\r
+#define PRV_S 1\r
+#define PRV_H 2\r
+#define PRV_M 3\r
+\r
+#define VM_MBARE 0\r
+#define VM_MBB 1\r
+#define VM_MBBID 2\r
+#define VM_SV32 8\r
+#define VM_SV39 9\r
+#define VM_SV48 10\r
+\r
+#define IRQ_S_SOFT 1\r
+#define IRQ_H_SOFT 2\r
+#define IRQ_M_SOFT 3\r
+#define IRQ_S_TIMER 5\r
+#define IRQ_H_TIMER 6\r
+#define IRQ_M_TIMER 7\r
+#define IRQ_S_EXT 9\r
+#define IRQ_H_EXT 10\r
+#define IRQ_M_EXT 11\r
+\r
+#define DEFAULT_RSTVEC 0x00001000\r
+#define DEFAULT_NMIVEC 0x00001004\r
+#define DEFAULT_MTVEC 0x00001010\r
+#define CONFIG_STRING_ADDR 0x0000100C\r
+#define EXT_IO_BASE 0x40000000\r
+#define DRAM_BASE 0x80000000\r
+\r
+/* page table entry (PTE) fields */\r
+#define PTE_V 0x001 /* Valid */\r
+#define PTE_TYPE 0x01E /* Type */\r
+#define PTE_R 0x020 /* Referenced */\r
+#define PTE_D 0x040 /* Dirty */\r
+#define PTE_SOFT 0x380 /* Reserved for Software */\r
+\r
+#define PTE_TYPE_TABLE 0x00\r
+#define PTE_TYPE_TABLE_GLOBAL 0x02\r
+#define PTE_TYPE_URX_SR 0x04\r
+#define PTE_TYPE_URWX_SRW 0x06\r
+#define PTE_TYPE_UR_SR 0x08\r
+#define PTE_TYPE_URW_SRW 0x0A\r
+#define PTE_TYPE_URX_SRX 0x0C\r
+#define PTE_TYPE_URWX_SRWX 0x0E\r
+#define PTE_TYPE_SR 0x10\r
+#define PTE_TYPE_SRW 0x12\r
+#define PTE_TYPE_SRX 0x14\r
+#define PTE_TYPE_SRWX 0x16\r
+#define PTE_TYPE_SR_GLOBAL 0x18\r
+#define PTE_TYPE_SRW_GLOBAL 0x1A\r
+#define PTE_TYPE_SRX_GLOBAL 0x1C\r
+#define PTE_TYPE_SRWX_GLOBAL 0x1E\r
+\r
+#define PTE_PPN_SHIFT 10\r
+\r
+#define PTE_TABLE(PTE) ((0x0000000AU >> ((PTE) & 0x1F)) & 1)\r
+#define PTE_UR(PTE) ((0x0000AAA0U >> ((PTE) & 0x1F)) & 1)\r
+#define PTE_UW(PTE) ((0x00008880U >> ((PTE) & 0x1F)) & 1)\r
+#define PTE_UX(PTE) ((0x0000A0A0U >> ((PTE) & 0x1F)) & 1)\r
+#define PTE_SR(PTE) ((0xAAAAAAA0U >> ((PTE) & 0x1F)) & 1)\r
+#define PTE_SW(PTE) ((0x88888880U >> ((PTE) & 0x1F)) & 1)\r
+#define PTE_SX(PTE) ((0xA0A0A000U >> ((PTE) & 0x1F)) & 1)\r
+\r
+#define PTE_CHECK_PERM(PTE, SUPERVISOR, STORE, FETCH) \\r
+ ((STORE) ? ((SUPERVISOR) ? PTE_SW(PTE) : PTE_UW(PTE)) : \\r
+ (FETCH) ? ((SUPERVISOR) ? PTE_SX(PTE) : PTE_UX(PTE)) : \\r
+ ((SUPERVISOR) ? PTE_SR(PTE) : PTE_UR(PTE)))\r
+\r
+#ifdef __riscv\r
+\r
+#if __riscv_xlen == 64\r
+# define MSTATUS_SD MSTATUS64_SD\r
+# define SSTATUS_SD SSTATUS64_SD\r
+# define MCAUSE_INT MCAUSE64_INT\r
+# define MCAUSE_CAUSE MCAUSE64_CAUSE\r
+# define RISCV_PGLEVEL_BITS 9\r
+#else\r
+# define MSTATUS_SD MSTATUS32_SD\r
+# define SSTATUS_SD SSTATUS32_SD\r
+# define RISCV_PGLEVEL_BITS 10\r
+# define MCAUSE_INT MCAUSE32_INT\r
+# define MCAUSE_CAUSE MCAUSE32_CAUSE\r
+#endif\r
+\r
+#define RISCV_PGSHIFT 12\r
+#define RISCV_PGSIZE (1 << RISCV_PGSHIFT)\r
+\r
+#ifndef __ASSEMBLER__\r
+\r
+#ifdef __GNUC__\r
+\r
+#define read_csr(reg) ({ unsigned long __tmp; \\r
+ asm volatile ("csrr %0, " #reg : "=r"(__tmp)); \\r
+ __tmp; })\r
+\r
+#define write_csr(reg, val) ({ \\r
+ if (__builtin_constant_p(val) && (unsigned long)(val) < 32) \\r
+ asm volatile ("csrw " #reg ", %0" :: "i"(val)); \\r
+ else \\r
+ asm volatile ("csrw " #reg ", %0" :: "r"(val)); })\r
+\r
+#define swap_csr(reg, val) ({ unsigned long __tmp; \\r
+ if (__builtin_constant_p(val) && (unsigned long)(val) < 32) \\r
+ asm volatile ("csrrw %0, " #reg ", %1" : "=r"(__tmp) : "i"(val)); \\r
+ else \\r
+ asm volatile ("csrrw %0, " #reg ", %1" : "=r"(__tmp) : "r"(val)); \\r
+ __tmp; })\r
+\r
+#define set_csr(reg, bit) ({ unsigned long __tmp; \\r
+ if (__builtin_constant_p(bit) && (unsigned long)(bit) < 32) \\r
+ asm volatile ("csrrs %0, " #reg ", %1" : "=r"(__tmp) : "i"(bit)); \\r
+ else \\r
+ asm volatile ("csrrs %0, " #reg ", %1" : "=r"(__tmp) : "r"(bit)); \\r
+ __tmp; })\r
+\r
+#define clear_csr(reg, bit) ({ unsigned long __tmp; \\r
+ if (__builtin_constant_p(bit) && (unsigned long)(bit) < 32) \\r
+ asm volatile ("csrrc %0, " #reg ", %1" : "=r"(__tmp) : "i"(bit)); \\r
+ else \\r
+ asm volatile ("csrrc %0, " #reg ", %1" : "=r"(__tmp) : "r"(bit)); \\r
+ __tmp; })\r
+\r
+#define rdtime() read_csr(time)\r
+#define rdcycle() read_csr(cycle)\r
+#define rdinstret() read_csr(instret)\r
+\r
+#ifdef __riscv_atomic\r
+\r
+#define MASK(nr) (1UL << nr)\r
+#define MASK_NOT(nr) (~(1UL << nr))\r
+\r
+/**\r
+ * atomic_read - read atomic variable\r
+ * @v: pointer of type int\r
+ *\r
+ * Atomically reads the value of @v.\r
+ */\r
+static inline int atomic_read(const int *v)\r
+{\r
+ return *((volatile int *)(v));\r
+}\r
+\r
+/**\r
+ * atomic_set - set atomic variable\r
+ * @v: pointer of type int\r
+ * @i: required value\r
+ *\r
+ * Atomically sets the value of @v to @i.\r
+ */\r
+static inline void atomic_set(int *v, int i)\r
+{\r
+ *v = i;\r
+}\r
+\r
+/**\r
+ * atomic_add - add integer to atomic variable\r
+ * @i: integer value to add\r
+ * @v: pointer of type int\r
+ *\r
+ * Atomically adds @i to @v.\r
+ */\r
+static inline void atomic_add(int i, int *v)\r
+{\r
+ __asm__ __volatile__ (\r
+ "amoadd.w zero, %1, %0"\r
+ : "+A" (*v)\r
+ : "r" (i));\r
+}\r
+\r
+static inline int atomic_fetch_add(unsigned int mask, int *v)\r
+{\r
+ int out;\r
+\r
+ __asm__ __volatile__ (\r
+ "amoadd.w %2, %1, %0"\r
+ : "+A" (*v), "=r" (out)\r
+ : "r" (mask));\r
+ return out;\r
+}\r
+\r
+/**\r
+ * atomic_sub - subtract integer from atomic variable\r
+ * @i: integer value to subtract\r
+ * @v: pointer of type int\r
+ *\r
+ * Atomically subtracts @i from @v.\r
+ */\r
+static inline void atomic_sub(int i, int *v)\r
+{\r
+ atomic_add(-i, v);\r
+}\r
+\r
+static inline int atomic_fetch_sub(unsigned int mask, int *v)\r
+{\r
+ int out;\r
+\r
+ __asm__ __volatile__ (\r
+ "amosub.w %2, %1, %0"\r
+ : "+A" (*v), "=r" (out)\r
+ : "r" (mask));\r
+ return out;\r
+}\r
+\r
+/**\r
+ * atomic_add_return - add integer to atomic variable\r
+ * @i: integer value to add\r
+ * @v: pointer of type int\r
+ *\r
+ * Atomically adds @i to @v and returns the result\r
+ */\r
+static inline int atomic_add_return(int i, int *v)\r
+{\r
+ register int c;\r
+ __asm__ __volatile__ (\r
+ "amoadd.w %0, %2, %1"\r
+ : "=r" (c), "+A" (*v)\r
+ : "r" (i));\r
+ return (c + i);\r
+}\r
+\r
+/**\r
+ * atomic_sub_return - subtract integer from atomic variable\r
+ * @i: integer value to subtract\r
+ * @v: pointer of type int\r
+ *\r
+ * Atomically subtracts @i from @v and returns the result\r
+ */\r
+static inline int atomic_sub_return(int i, int *v)\r
+{\r
+ return atomic_add_return(-i, v);\r
+}\r
+\r
+/**\r
+ * atomic_inc - increment atomic variable\r
+ * @v: pointer of type int\r
+ *\r
+ * Atomically increments @v by 1.\r
+ */\r
+static inline void atomic_inc(int *v)\r
+{\r
+ atomic_add(1, v);\r
+}\r
+\r
+/**\r
+ * atomic_dec - decrement atomic variable\r
+ * @v: pointer of type int\r
+ *\r
+ * Atomically decrements @v by 1.\r
+ */\r
+static inline void atomic_dec(int *v)\r
+{\r
+ atomic_add(-1, v);\r
+}\r
+\r
+static inline int atomic_inc_return(int *v)\r
+{\r
+ return atomic_add_return(1, v);\r
+}\r
+\r
+static inline int atomic_dec_return(int *v)\r
+{\r
+ return atomic_sub_return(1, v);\r
+}\r
+\r
+/**\r
+ * atomic_sub_and_test - subtract value from variable and test result\r
+ * @i: integer value to subtract\r
+ * @v: pointer of type int\r
+ *\r
+ * Atomically subtracts @i from @v and returns\r
+ * true if the result is zero, or false for all\r
+ * other cases.\r
+ */\r
+static inline int atomic_sub_and_test(int i, int *v)\r
+{\r
+ return (atomic_sub_return(i, v) == 0);\r
+}\r
+\r
+/**\r
+ * atomic_inc_and_test - increment and test\r
+ * @v: pointer of type int\r
+ *\r
+ * Atomically increments @v by 1\r
+ * and returns true if the result is zero, or false for all\r
+ * other cases.\r
+ */\r
+static inline int atomic_inc_and_test(int *v)\r
+{\r
+ return (atomic_inc_return(v) == 0);\r
+}\r
+\r
+/**\r
+ * atomic_dec_and_test - decrement and test\r
+ * @v: pointer of type int\r
+ *\r
+ * Atomically decrements @v by 1 and\r
+ * returns true if the result is 0, or false for all other\r
+ * cases.\r
+ */\r
+static inline int atomic_dec_and_test(int *v)\r
+{\r
+ return (atomic_dec_return(v) == 0);\r
+}\r
+\r
+/**\r
+ * atomic_add_negative - add and test if negative\r
+ * @i: integer value to add\r
+ * @v: pointer of type int\r
+ *\r
+ * Atomically adds @i to @v and returns true\r
+ * if the result is negative, or false when\r
+ * result is greater than or equal to zero.\r
+ */\r
+static inline int atomic_add_negative(int i, int *v)\r
+{\r
+ return (atomic_add_return(i, v) < 0);\r
+}\r
+\r
+static inline int atomic_xchg(int *v, int n)\r
+{\r
+ register int c;\r
+ __asm__ __volatile__ (\r
+ "amoswap.w %0, %2, %1"\r
+ : "=r" (c), "+A" (*v)\r
+ : "r" (n));\r
+ return c;\r
+}\r
+\r
+/**\r
+ * atomic_and - Atomically clear bits in atomic variable\r
+ * @mask: Mask of the bits to be retained\r
+ * @v: pointer of type int\r
+ *\r
+ * Atomically retains the bits set in @mask from @v\r
+ */\r
+static inline void atomic_and(unsigned int mask, int *v)\r
+{\r
+ __asm__ __volatile__ (\r
+ "amoand.w zero, %1, %0"\r
+ : "+A" (*v)\r
+ : "r" (mask));\r
+}\r
+\r
+static inline int atomic_fetch_and(unsigned int mask, int *v)\r
+{\r
+ int out;\r
+ __asm__ __volatile__ (\r
+ "amoand.w %2, %1, %0"\r
+ : "+A" (*v), "=r" (out)\r
+ : "r" (mask));\r
+ return out;\r
+}\r
+\r
+/**\r
+ * atomic_or - Atomically set bits in atomic variable\r
+ * @mask: Mask of the bits to be set\r
+ * @v: pointer of type int\r
+ *\r
+ * Atomically sets the bits set in @mask in @v\r
+ */\r
+static inline void atomic_or(unsigned int mask, int *v)\r
+{\r
+ __asm__ __volatile__ (\r
+ "amoor.w zero, %1, %0"\r
+ : "+A" (*v)\r
+ : "r" (mask));\r
+}\r
+\r
+static inline int atomic_fetch_or(unsigned int mask, int *v)\r
+{\r
+ int out;\r
+ __asm__ __volatile__ (\r
+ "amoor.w %2, %1, %0"\r
+ : "+A" (*v), "=r" (out)\r
+ : "r" (mask));\r
+ return out;\r
+}\r
+\r
+/**\r
+ * atomic_xor - Atomically flips bits in atomic variable\r
+ * @mask: Mask of the bits to be flipped\r
+ * @v: pointer of type int\r
+ *\r
+ * Atomically flips the bits set in @mask in @v\r
+ */\r
+static inline void atomic_xor(unsigned int mask, int *v)\r
+{\r
+ __asm__ __volatile__ (\r
+ "amoxor.w zero, %1, %0"\r
+ : "+A" (*v)\r
+ : "r" (mask));\r
+}\r
+\r
+static inline int atomic_fetch_xor(unsigned int mask, int *v)\r
+{\r
+ int out;\r
+ __asm__ __volatile__ (\r
+ "amoxor.w %2, %1, %0"\r
+ : "+A" (*v), "=r" (out)\r
+ : "r" (mask));\r
+ return out;\r
+}\r
+\r
+/*----------------------------------------------------*/\r
+\r
+/**\r
+ * test_and_set_bit - Set a bit and return its old value\r
+ * @nr: Bit to set\r
+ * @addr: Address to count from\r
+ *\r
+ * This operation is atomic and cannot be reordered.\r
+ * It also implies a memory barrier.\r
+ */\r
+static inline int test_and_set_bit(int nr, volatile unsigned long *addr)\r
+{\r
+ unsigned long __res, __mask;\r
+ __mask = MASK(nr);\r
+ __asm__ __volatile__ ( \\r
+ "amoor.w %0, %2, %1" \\r
+ : "=r" (__res), "+A" (*addr) \\r
+ : "r" (__mask)); \\r
+\r
+ return ((__res & __mask) != 0);\r
+}\r
+\r
+\r
+/**\r
+ * test_and_clear_bit - Clear a bit and return its old value\r
+ * @nr: Bit to clear\r
+ * @addr: Address to count from\r
+ *\r
+ * This operation is atomic and cannot be reordered.\r
+ * It also implies a memory barrier.\r
+ */\r
+static inline int test_and_clear_bit(int nr, volatile unsigned long *addr)\r
+{\r
+ unsigned long __res, __mask;\r
+ __mask = MASK_NOT(nr);\r
+ __asm__ __volatile__ ( \\r
+ "amoand.w %0, %2, %1" \\r
+ : "=r" (__res), "+A" (*addr) \\r
+ : "r" (__mask)); \\r
+\r
+ return ((__res & __mask) != 0);\r
+}\r
+\r
+/**\r
+ * test_and_change_bit - Change a bit and return its old value\r
+ * @nr: Bit to change\r
+ * @addr: Address to count from\r
+ *\r
+ * This operation is atomic and cannot be reordered.\r
+ * It also implies a memory barrier.\r
+ */\r
+static inline int test_and_change_bit(int nr, volatile unsigned long *addr)\r
+{\r
+\r
+ unsigned long __res, __mask;\r
+ __mask = MASK(nr);\r
+ __asm__ __volatile__ ( \\r
+ "amoxor.w %0, %2, %1" \\r
+ : "=r" (__res), "+A" (*addr) \\r
+ : "r" (__mask)); \\r
+\r
+ return ((__res & __mask) != 0);\r
+}\r
+\r
+/**\r
+ * set_bit - Atomically set a bit in memory\r
+ * @nr: the bit to set\r
+ * @addr: the address to start counting from\r
+ *\r
+ * This function is atomic and may not be reordered. \r
+ */\r
+\r
+static inline void set_bit(int nr, volatile unsigned long *addr)\r
+{\r
+ __asm__ __volatile__ ( \\r
+ "AMOOR.w zero, %1, %0" \\r
+ : "+A" (*addr) \\r
+ : "r" (MASK(nr)));\r
+}\r
+\r
+/**\r
+ * clear_bit - Clears a bit in memory\r
+ * @nr: Bit to clear\r
+ * @addr: Address to start counting from\r
+ *\r
+ * clear_bit() is atomic and may not be reordered. \r
+ */\r
+static inline void clear_bit(int nr, volatile unsigned long *addr)\r
+{\r
+ __asm__ __volatile__ ( \\r
+ "AMOAND.w zero, %1, %0" \\r
+ : "+A" (*addr) \\r
+ : "r" (MASK_NOT(nr)));\r
+}\r
+\r
+/**\r
+ * change_bit - Toggle a bit in memory\r
+ * @nr: Bit to change\r
+ * @addr: Address to start counting from\r
+ *\r
+ * change_bit() is atomic and may not be reordered.\r
+ */\r
+static inline void change_bit(int nr, volatile unsigned long *addr)\r
+{\r
+ __asm__ __volatile__ ( \\r
+ "AMOXOR.w zero, %1, %0" \\r
+ : "+A" (*addr) \\r
+ : "r" (MASK(nr)));\r
+}\r
+\r
+#endif /* __riscv_atomic */\r
+\r
+#endif /*__GNUC__*/\r
+\r
+#endif /*__ASSEMBLER__*/\r
+\r
+#endif /*__riscv*/\r
+\r
+#ifdef __cplusplus\r
+}\r
+#endif\r
+\r
+#endif /*RISCV_CSR_ENCODING_H*/\r
+\r
--- /dev/null
+/*******************************************************************************\r
+ * (c) Copyright 2016-2018 Microsemi SoC Products Group. All rights reserved.\r
+ *\r
+ * @file entry.S\r
+ * @author Microsemi SoC Products Group\r
+ * @brief Mi-V soft processor vectors, trap handling and startup code.\r
+ *\r
+ * SVN $Revision: 9947 $\r
+ * SVN $Date: 2018-04-30 20:28:49 +0530 (Mon, 30 Apr 2018) $\r
+ */\r
+#ifndef ENTRY_S\r
+#define ENTRY_S\r
+\r
+#include "encoding.h"\r
+\r
+#if __riscv_xlen == 64\r
+# define LREG ld\r
+# define SREG sd\r
+# define REGBYTES 8\r
+#else\r
+# define LREG lw\r
+# define SREG sw\r
+# define REGBYTES 4\r
+#endif\r
+\r
+ .section .text.entry\r
+ .globl _start\r
+\r
+_start:\r
+ j handle_reset\r
+\r
+nmi_vector:\r
+ j nmi_vector\r
+\r
+trap_vector:\r
+ j trap_entry\r
+\r
+handle_reset:\r
+ la t0, trap_entry\r
+ csrw mtvec, t0\r
+ csrwi mstatus, 0\r
+ csrwi mie, 0\r
+\r
+/*Floating point support configuration*/\r
+\r
+#ifdef __riscv_flen\r
+ csrr t0, mstatus\r
+ lui t1, 0xffffa\r
+ addi t1, t1, -1\r
+ and t0, t0, t1\r
+ lui t1, 0x4\r
+ or t1, t0, t1\r
+ csrw mstatus, t1\r
+\r
+ lui t0, 0x0\r
+ fscsr t0\r
+#endif\r
+.option push\r
+\r
+# Ensure the instruction is not optimized, since gp is not yet set\r
+\r
+.option norelax\r
+ # initialize global pointer\r
+ la gp, __global_pointer$\r
+\r
+.option pop\r
+\r
+ # initialize stack pointer\r
+ la sp, __stack_top\r
+\r
+ # perform the rest of initialization in C\r
+ j _init\r
+\r
+\r
+trap_entry:\r
+ addi sp, sp, -32*REGBYTES\r
+\r
+ SREG x1, 0 * REGBYTES(sp)\r
+ SREG x2, 1 * REGBYTES(sp)\r
+ SREG x3, 2 * REGBYTES(sp)\r
+ SREG x4, 3 * REGBYTES(sp)\r
+ SREG x5, 4 * REGBYTES(sp)\r
+ SREG x6, 5 * REGBYTES(sp)\r
+ SREG x7, 6 * REGBYTES(sp)\r
+ SREG x8, 7 * REGBYTES(sp)\r
+ SREG x9, 8 * REGBYTES(sp)\r
+ SREG x10, 9 * REGBYTES(sp)\r
+ SREG x11, 10 * REGBYTES(sp)\r
+ SREG x12, 11 * REGBYTES(sp)\r
+ SREG x13, 12 * REGBYTES(sp)\r
+ SREG x14, 13 * REGBYTES(sp)\r
+ SREG x15, 14 * REGBYTES(sp)\r
+ SREG x16, 15 * REGBYTES(sp)\r
+ SREG x17, 16 * REGBYTES(sp)\r
+ SREG x18, 17 * REGBYTES(sp)\r
+ SREG x19, 18 * REGBYTES(sp)\r
+ SREG x20, 19 * REGBYTES(sp)\r
+ SREG x21, 20 * REGBYTES(sp)\r
+ SREG x22, 21 * REGBYTES(sp)\r
+ SREG x23, 22 * REGBYTES(sp)\r
+ SREG x24, 23 * REGBYTES(sp)\r
+ SREG x25, 24 * REGBYTES(sp)\r
+ SREG x26, 25 * REGBYTES(sp)\r
+ SREG x27, 26 * REGBYTES(sp)\r
+ SREG x28, 27 * REGBYTES(sp)\r
+ SREG x29, 28 * REGBYTES(sp)\r
+ SREG x30, 29 * REGBYTES(sp)\r
+ SREG x31, 30 * REGBYTES(sp)\r
+\r
+\r
+ csrr t0, mepc\r
+ SREG t0, 31 * REGBYTES(sp)\r
+\r
+ csrr a0, mcause\r
+ csrr a1, mepc\r
+ mv a2, sp\r
+ jal handle_trap\r
+ csrw mepc, a0\r
+\r
+ # Remain in M-mode after mret\r
+ li t0, MSTATUS_MPP\r
+ csrs mstatus, t0\r
+\r
+ LREG x1, 0 * REGBYTES(sp)\r
+ LREG x2, 1 * REGBYTES(sp)\r
+ LREG x3, 2 * REGBYTES(sp)\r
+ LREG x4, 3 * REGBYTES(sp)\r
+ LREG x5, 4 * REGBYTES(sp)\r
+ LREG x6, 5 * REGBYTES(sp)\r
+ LREG x7, 6 * REGBYTES(sp)\r
+ LREG x8, 7 * REGBYTES(sp)\r
+ LREG x9, 8 * REGBYTES(sp)\r
+ LREG x10, 9 * REGBYTES(sp)\r
+ LREG x11, 10 * REGBYTES(sp)\r
+ LREG x12, 11 * REGBYTES(sp)\r
+ LREG x13, 12 * REGBYTES(sp)\r
+ LREG x14, 13 * REGBYTES(sp)\r
+ LREG x15, 14 * REGBYTES(sp)\r
+ LREG x16, 15 * REGBYTES(sp)\r
+ LREG x17, 16 * REGBYTES(sp)\r
+ LREG x18, 17 * REGBYTES(sp)\r
+ LREG x19, 18 * REGBYTES(sp)\r
+ LREG x20, 19 * REGBYTES(sp)\r
+ LREG x21, 20 * REGBYTES(sp)\r
+ LREG x22, 21 * REGBYTES(sp)\r
+ LREG x23, 22 * REGBYTES(sp)\r
+ LREG x24, 23 * REGBYTES(sp)\r
+ LREG x25, 24 * REGBYTES(sp)\r
+ LREG x26, 25 * REGBYTES(sp)\r
+ LREG x27, 26 * REGBYTES(sp)\r
+ LREG x28, 27 * REGBYTES(sp)\r
+ LREG x29, 28 * REGBYTES(sp)\r
+ LREG x30, 29 * REGBYTES(sp)\r
+ LREG x31, 30 * REGBYTES(sp)\r
+\r
+ addi sp, sp, 32*REGBYTES\r
+ mret\r
+\r
+#endif\r
+\r
--- /dev/null
+/*******************************************************************************\r
+ * (c) Copyright 2016-2018 Microsemi SoC Products Group. All rights reserved.\r
+ *\r
+ * @file init.c\r
+ * @author Microsemi SoC Products Group\r
+ * @brief Mi-V soft processor memory section initializations and start-up code.\r
+ *\r
+ * SVN $Revision: 9661 $\r
+ * SVN $Date: 2018-01-15 16:13:33 +0530 (Mon, 15 Jan 2018) $\r
+ */\r
+\r
+#include <stdlib.h>\r
+#include <stdint.h>\r
+#include <unistd.h>\r
+\r
+#include "encoding.h"\r
+\r
+#ifdef __cplusplus\r
+extern "C" {\r
+#endif\r
+\r
+extern uint32_t __sdata_load;\r
+extern uint32_t __sdata_start;\r
+extern uint32_t __sdata_end;\r
+\r
+extern uint32_t __data_load;\r
+extern uint32_t __data_start;\r
+extern uint32_t __data_end;\r
+\r
+extern uint32_t __sbss_start;\r
+extern uint32_t __sbss_end;\r
+extern uint32_t __bss_start;\r
+extern uint32_t __bss_end;\r
+\r
+\r
+static void copy_section(uint32_t * p_load, uint32_t * p_vma, uint32_t * p_vma_end)\r
+{\r
+ while(p_vma <= p_vma_end)\r
+ {\r
+ *p_vma = *p_load;\r
+ ++p_load;\r
+ ++p_vma;\r
+ }\r
+}\r
+\r
+static void zero_section(uint32_t * start, uint32_t * end)\r
+{\r
+ uint32_t * p_zero = start;\r
+ \r
+ while(p_zero <= end)\r
+ {\r
+ *p_zero = 0;\r
+ ++p_zero;\r
+ }\r
+}\r
+\r
+void _init(void)\r
+{\r
+ extern int main(int, char**);\r
+ const char *argv0 = "hello";\r
+ char *argv[] = {(char *)argv0, NULL, NULL};\r
+\r
+ copy_section(&__sdata_load, &__sdata_start, &__sdata_end);\r
+ copy_section(&__data_load, &__data_start, &__data_end);\r
+ zero_section(&__sbss_start, &__sbss_end);\r
+ zero_section(&__bss_start, &__bss_end);\r
+ \r
+ main(1, argv);\r
+}\r
+\r
+/* Function called after main() finishes */\r
+void\r
+_fini()\r
+{\r
+}\r
+\r
+#ifdef __cplusplus\r
+}\r
+#endif\r
+\r
--- /dev/null
+/*******************************************************************************\r
+ * (c) Copyright 2016-2018 Microsemi SoC Products Group. All rights reserved.\r
+ * \r
+ * file name : microsemi-riscv-igloo2.ld\r
+ * Mi-V soft processor linker script for creating a SoftConsole downloadable\r
+ * image executing in eNVM.\r
+ * \r
+ * This linker script assumes that the eNVM is connected at on the Mi-V soft\r
+ * processor memory space. \r
+ *\r
+ * SVN $Revision: 9661 $\r
+ * SVN $Date: 2018-01-15 16:13:33 +0530 (Mon, 15 Jan 2018) $\r
+ */\r
+ \r
+OUTPUT_ARCH( "riscv" )\r
+ENTRY(_start)\r
+\r
+\r
+MEMORY\r
+{\r
+ envm (rx) : ORIGIN = 0x60000000, LENGTH = 240k\r
+ ram (rwx) : ORIGIN = 0x80000000, LENGTH = 64k\r
+}\r
+\r
+RAM_START_ADDRESS = 0x80000000; /* Must be the same value MEMORY region ram ORIGIN above. */\r
+RAM_SIZE = 64k; /* Must be the same value MEMORY region ram LENGTH above. */\r
+STACK_SIZE = 2k; /* needs to be calculated for your application */ \r
+HEAP_SIZE = 2k; /* needs to be calculated for your application */\r
+\r
+SECTIONS\r
+{\r
+ .text : ALIGN(0x10)\r
+ {\r
+ KEEP (*(SORT_NONE(.text.entry))) \r
+ . = ALIGN(0x10);\r
+ *(.text .text.* .gnu.linkonce.t.*)\r
+ *(.plt)\r
+ . = ALIGN(0x10);\r
+ \r
+ KEEP (*crtbegin.o(.ctors))\r
+ KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors))\r
+ KEEP (*(SORT(.ctors.*)))\r
+ KEEP (*crtend.o(.ctors))\r
+ KEEP (*crtbegin.o(.dtors))\r
+ KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors))\r
+ KEEP (*(SORT(.dtors.*)))\r
+ KEEP (*crtend.o(.dtors))\r
+ \r
+ *(.rodata .rodata.* .gnu.linkonce.r.*)\r
+ *(.gcc_except_table) \r
+ *(.eh_frame_hdr)\r
+ *(.eh_frame)\r
+ \r
+ KEEP (*(.init))\r
+ KEEP (*(.fini))\r
+\r
+ PROVIDE_HIDDEN (__preinit_array_start = .);\r
+ KEEP (*(.preinit_array))\r
+ PROVIDE_HIDDEN (__preinit_array_end = .);\r
+ PROVIDE_HIDDEN (__init_array_start = .);\r
+ KEEP (*(SORT(.init_array.*)))\r
+ KEEP (*(.init_array))\r
+ PROVIDE_HIDDEN (__init_array_end = .);\r
+ PROVIDE_HIDDEN (__fini_array_start = .);\r
+ KEEP (*(.fini_array))\r
+ KEEP (*(SORT(.fini_array.*)))\r
+ PROVIDE_HIDDEN (__fini_array_end = .);\r
+ . = ALIGN(0x10);\r
+ \r
+ } >envm\r
+\r
+ /* short/global data section */\r
+ .sdata : ALIGN(0x10)\r
+ {\r
+ __sdata_load = LOADADDR(.sdata);\r
+ __sdata_start = .; \r
+ PROVIDE( __global_pointer$ = . + 0x800);\r
+ *(.srodata.cst16) *(.srodata.cst8) *(.srodata.cst4) *(.srodata.cst2)\r
+ *(.srodata*)\r
+ *(.sdata .sdata.* .gnu.linkonce.s.*)\r
+ . = ALIGN(0x10);\r
+ __sdata_end = .;\r
+ } >ram AT>envm\r
+\r
+ /* data section */\r
+ .data : ALIGN(0x10)\r
+ { \r
+ __data_load = LOADADDR(.data);\r
+ __data_start = .; \r
+ *(.got.plt) *(.got)\r
+ *(.shdata)\r
+ *(.data .data.* .gnu.linkonce.d.*)\r
+ . = ALIGN(0x10);\r
+ __data_end = .;\r
+ } >ram AT>envm\r
+\r
+ /* sbss section */\r
+ .sbss : ALIGN(0x10)\r
+ {\r
+ __sbss_start = .;\r
+ *(.sbss .sbss.* .gnu.linkonce.sb.*)\r
+ *(.scommon)\r
+ . = ALIGN(0x10);\r
+ __sbss_end = .;\r
+ } > ram\r
+ \r
+ /* sbss section */\r
+ .bss : ALIGN(0x10)\r
+ { \r
+ __bss_start = .;\r
+ *(.shbss)\r
+ *(.bss .bss.* .gnu.linkonce.b.*)\r
+ *(COMMON)\r
+ . = ALIGN(0x10);\r
+ __bss_end = .;\r
+ } > ram\r
+\r
+ /* End of uninitialized data segment */\r
+ _end = .;\r
+ \r
+ .heap : ALIGN(0x10)\r
+ {\r
+ __heap_start = .;\r
+ . += HEAP_SIZE;\r
+ __heap_end = .;\r
+ . = ALIGN(0x10);\r
+ _heap_end = __heap_end;\r
+ } > ram\r
+ \r
+ .stack : ALIGN(0x10)\r
+ {\r
+ __stack_bottom = .;\r
+ . += STACK_SIZE;\r
+ __stack_top = .;\r
+ } > ram\r
+}\r
+\r
--- /dev/null
+/*******************************************************************************\r
+ * (c) Copyright 2016-2018 Microsemi SoC Products Group. All rights reserved.\r
+ * \r
+ * file name : microsemi-riscv-ram.ld\r
+ * Mi-V soft processor linker script for creating a SoftConsole downloadable\r
+ * debug image executing in SRAM.\r
+ * \r
+ * This linker script assumes that the SRAM is connected at on the Mi-V soft\r
+ * processor memory space. The start address and size of the memory space must\r
+ * be correct as per the Libero design.\r
+ *\r
+ * SVN $Revision: 9661 $\r
+ * SVN $Date: 2018-01-15 16:13:33 +0530 (Mon, 15 Jan 2018) $\r
+ */\r
+ \r
+OUTPUT_ARCH( "riscv" )\r
+ENTRY(_start)\r
+\r
+\r
+MEMORY\r
+{\r
+ ram (rwx) : ORIGIN = 0x80000000, LENGTH = 512k\r
+}\r
+\r
+RAM_START_ADDRESS = 0x80000000; /* Must be the same value MEMORY region ram ORIGIN above. */\r
+RAM_SIZE = 512k; /* Must be the same value MEMORY region ram LENGTH above. */\r
+STACK_SIZE = 64k; /* needs to be calculated for your application */ \r
+HEAP_SIZE = 64k; /* needs to be calculated for your application */\r
+\r
+SECTIONS\r
+{\r
+ .text : ALIGN(0x10)\r
+ {\r
+ KEEP (*(SORT_NONE(.text.entry))) \r
+ . = ALIGN(0x10);\r
+ *(.text .text.* .gnu.linkonce.t.*)\r
+ *(.plt)\r
+ . = ALIGN(0x10);\r
+ \r
+ KEEP (*crtbegin.o(.ctors))\r
+ KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors))\r
+ KEEP (*(SORT(.ctors.*)))\r
+ KEEP (*crtend.o(.ctors))\r
+ KEEP (*crtbegin.o(.dtors))\r
+ KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors))\r
+ KEEP (*(SORT(.dtors.*)))\r
+ KEEP (*crtend.o(.dtors))\r
+ \r
+ *(.rodata .rodata.* .gnu.linkonce.r.*)\r
+ *(.gcc_except_table) \r
+ *(.eh_frame_hdr)\r
+ *(.eh_frame)\r
+ \r
+ KEEP (*(.init))\r
+ KEEP (*(.fini))\r
+\r
+ PROVIDE_HIDDEN (__preinit_array_start = .);\r
+ KEEP (*(.preinit_array))\r
+ PROVIDE_HIDDEN (__preinit_array_end = .);\r
+ PROVIDE_HIDDEN (__init_array_start = .);\r
+ KEEP (*(SORT(.init_array.*)))\r
+ KEEP (*(.init_array))\r
+ PROVIDE_HIDDEN (__init_array_end = .);\r
+ PROVIDE_HIDDEN (__fini_array_start = .);\r
+ KEEP (*(.fini_array))\r
+ KEEP (*(SORT(.fini_array.*)))\r
+ PROVIDE_HIDDEN (__fini_array_end = .);\r
+ . = ALIGN(0x10);\r
+ \r
+ } > ram\r
+\r
+ /* short/global data section */\r
+ .sdata : ALIGN(0x10)\r
+ {\r
+ __sdata_load = LOADADDR(.sdata);\r
+ __sdata_start = .; \r
+ PROVIDE( __global_pointer$ = . + 0x800);\r
+ *(.srodata.cst16) *(.srodata.cst8) *(.srodata.cst4) *(.srodata.cst2)\r
+ *(.srodata*)\r
+ *(.sdata .sdata.* .gnu.linkonce.s.*)\r
+ . = ALIGN(0x10);\r
+ __sdata_end = .;\r
+ } > ram\r
+\r
+ /* data section */\r
+ .data : ALIGN(0x10)\r
+ { \r
+ __data_load = LOADADDR(.data);\r
+ __data_start = .; \r
+ *(.got.plt) *(.got)\r
+ *(.shdata)\r
+ *(.data .data.* .gnu.linkonce.d.*)\r
+ . = ALIGN(0x10);\r
+ __data_end = .;\r
+ } > ram\r
+\r
+ /* sbss section */\r
+ .sbss : ALIGN(0x10)\r
+ {\r
+ __sbss_start = .;\r
+ *(.sbss .sbss.* .gnu.linkonce.sb.*)\r
+ *(.scommon)\r
+ . = ALIGN(0x10);\r
+ __sbss_end = .;\r
+ } > ram\r
+ \r
+ /* sbss section */\r
+ .bss : ALIGN(0x10)\r
+ { \r
+ __bss_start = .;\r
+ *(.shbss)\r
+ *(.bss .bss.* .gnu.linkonce.b.*)\r
+ *(COMMON)\r
+ . = ALIGN(0x10);\r
+ __bss_end = .;\r
+ } > ram\r
+\r
+ /* End of uninitialized data segment */\r
+ _end = .;\r
+ \r
+ .heap : ALIGN(0x10)\r
+ {\r
+ __heap_start = .;\r
+ . += HEAP_SIZE;\r
+ __heap_end = .;\r
+ . = ALIGN(0x10);\r
+ _heap_end = __heap_end;\r
+ } > ram\r
+ \r
+ .stack : ALIGN(0x10)\r
+ {\r
+ __stack_bottom = .;\r
+ . += STACK_SIZE;\r
+ __stack_top = .;\r
+ } > ram\r
+}\r
+\r
--- /dev/null
+/*******************************************************************************\r
+ * (c) Copyright 2016-2018 Microsemi SoC Products Group. All rights reserved.\r
+ *\r
+ * @file riscv_hal.c\r
+ * @author Microsemi SoC Products Group\r
+ * @brief Implementation of Hardware Abstraction Layer for Mi-V soft processors\r
+ *\r
+ * SVN $Revision: 9835 $\r
+ * SVN $Date: 2018-03-19 19:11:35 +0530 (Mon, 19 Mar 2018) $\r
+ */\r
+#include <stdlib.h>\r
+#include <stdint.h>\r
+#include <unistd.h>\r
+\r
+#include "riscv_hal.h"\r
+\r
+#ifdef __cplusplus\r
+extern "C" {\r
+#endif\r
+\r
+#define RTC_PRESCALER 100UL\r
+\r
+#define SUCCESS 0U\r
+#define ERROR 1U\r
+\r
+/*------------------------------------------------------------------------------\r
+ *\r
+ */\r
+uint8_t Invalid_IRQHandler(void);\r
+uint8_t External_1_IRQHandler(void);\r
+uint8_t External_2_IRQHandler(void);\r
+uint8_t External_3_IRQHandler(void);\r
+uint8_t External_4_IRQHandler(void);\r
+uint8_t External_5_IRQHandler(void);\r
+uint8_t External_6_IRQHandler(void);\r
+uint8_t External_7_IRQHandler(void);\r
+uint8_t External_8_IRQHandler(void);\r
+uint8_t External_9_IRQHandler(void);\r
+uint8_t External_10_IRQHandler(void);\r
+uint8_t External_11_IRQHandler(void);\r
+uint8_t External_12_IRQHandler(void);\r
+uint8_t External_13_IRQHandler(void);\r
+uint8_t External_14_IRQHandler(void);\r
+uint8_t External_15_IRQHandler(void);\r
+uint8_t External_16_IRQHandler(void);\r
+uint8_t External_17_IRQHandler(void);\r
+uint8_t External_18_IRQHandler(void);\r
+uint8_t External_19_IRQHandler(void);\r
+uint8_t External_20_IRQHandler(void);\r
+uint8_t External_21_IRQHandler(void);\r
+uint8_t External_22_IRQHandler(void);\r
+uint8_t External_23_IRQHandler(void);\r
+uint8_t External_24_IRQHandler(void);\r
+uint8_t External_25_IRQHandler(void);\r
+uint8_t External_26_IRQHandler(void);\r
+uint8_t External_27_IRQHandler(void);\r
+uint8_t External_28_IRQHandler(void);\r
+uint8_t External_29_IRQHandler(void);\r
+uint8_t External_30_IRQHandler(void);\r
+uint8_t External_31_IRQHandler(void);\r
+\r
+/*------------------------------------------------------------------------------\r
+ *\r
+ */\r
+extern void Software_IRQHandler(void);\r
+\r
+/*------------------------------------------------------------------------------\r
+ * Increment value for the mtimecmp register in order to achieve a system tick\r
+ * interrupt as specified through the SysTick_Config() function.\r
+ */\r
+static uint64_t g_systick_increment = 0U;\r
+\r
+/*------------------------------------------------------------------------------\r
+ * Disable all interrupts.\r
+ */\r
+void __disable_irq(void)\r
+{\r
+ clear_csr(mstatus, MSTATUS_MPIE);\r
+ clear_csr(mstatus, MSTATUS_MIE);\r
+}\r
+\r
+/*------------------------------------------------------------------------------\r
+ * Enabler all interrupts.\r
+ */\r
+void __enable_irq(void)\r
+{\r
+ set_csr(mstatus, MSTATUS_MIE);\r
+}\r
+\r
+/*------------------------------------------------------------------------------\r
+ * Configure the machine timer to generate an interrupt.\r
+ */\r
+uint32_t SysTick_Config(uint32_t ticks)\r
+{\r
+ uint32_t ret_val = ERROR;\r
+\r
+ g_systick_increment = (uint64_t)(ticks) / RTC_PRESCALER;\r
+\r
+ if (g_systick_increment > 0U)\r
+ {\r
+ uint32_t mhart_id = read_csr(mhartid);\r
+\r
+ PRCI->MTIMECMP[mhart_id] = PRCI->MTIME + g_systick_increment;\r
+\r
+ set_csr(mie, MIP_MTIP);\r
+\r
+ __enable_irq();\r
+\r
+ ret_val = SUCCESS;\r
+ }\r
+\r
+ return ret_val;\r
+}\r
+\r
+/*------------------------------------------------------------------------------\r
+ * RISC-V interrupt handler for machine timer interrupts.\r
+ */\r
+static void handle_m_timer_interrupt(void)\r
+{\r
+ clear_csr(mie, MIP_MTIP);\r
+\r
+ SysTick_Handler();\r
+\r
+ PRCI->MTIMECMP[read_csr(mhartid)] = PRCI->MTIME + g_systick_increment;\r
+\r
+ set_csr(mie, MIP_MTIP);\r
+}\r
+\r
+/*------------------------------------------------------------------------------\r
+ * RISC-V interrupt handler for external interrupts.\r
+ */\r
+uint8_t (*ext_irq_handler_table[32])(void) =\r
+{\r
+ Invalid_IRQHandler,\r
+ External_1_IRQHandler,\r
+ External_2_IRQHandler,\r
+ External_3_IRQHandler,\r
+ External_4_IRQHandler,\r
+ External_5_IRQHandler,\r
+ External_6_IRQHandler,\r
+ External_7_IRQHandler,\r
+ External_8_IRQHandler,\r
+ External_9_IRQHandler,\r
+ External_10_IRQHandler,\r
+ External_11_IRQHandler,\r
+ External_12_IRQHandler,\r
+ External_13_IRQHandler,\r
+ External_14_IRQHandler,\r
+ External_15_IRQHandler,\r
+ External_16_IRQHandler,\r
+ External_17_IRQHandler,\r
+ External_18_IRQHandler,\r
+ External_19_IRQHandler,\r
+ External_20_IRQHandler,\r
+ External_21_IRQHandler,\r
+ External_22_IRQHandler,\r
+ External_23_IRQHandler,\r
+ External_24_IRQHandler,\r
+ External_25_IRQHandler,\r
+ External_26_IRQHandler,\r
+ External_27_IRQHandler,\r
+ External_28_IRQHandler,\r
+ External_29_IRQHandler,\r
+ External_30_IRQHandler,\r
+ External_31_IRQHandler\r
+};\r
+\r
+/*------------------------------------------------------------------------------\r
+ *\r
+ */\r
+static void handle_m_ext_interrupt(void)\r
+{\r
+ uint32_t int_num = PLIC_ClaimIRQ();\r
+ uint8_t disable = EXT_IRQ_KEEP_ENABLED;\r
+\r
+ disable = ext_irq_handler_table[int_num]();\r
+\r
+ PLIC_CompleteIRQ(int_num);\r
+\r
+ if(EXT_IRQ_DISABLE == disable)\r
+ {\r
+ PLIC_DisableIRQ((IRQn_Type)int_num);\r
+ }\r
+}\r
+\r
+static void handle_m_soft_interrupt(void)\r
+{\r
+ Software_IRQHandler();\r
+\r
+ /*Clear software interrupt*/\r
+ PRCI->MSIP[0] = 0x00U;\r
+}\r
+\r
+/*------------------------------------------------------------------------------\r
+ * Trap/Interrupt handler\r
+ */\r
+uintptr_t handle_trap(uintptr_t mcause, uintptr_t mepc)\r
+{\r
+ if ((mcause & MCAUSE_INT) && ((mcause & MCAUSE_CAUSE) == IRQ_M_EXT))\r
+ {\r
+ handle_m_ext_interrupt();\r
+ }\r
+ else if ((mcause & MCAUSE_INT) && ((mcause & MCAUSE_CAUSE) == IRQ_M_TIMER))\r
+ {\r
+ handle_m_timer_interrupt();\r
+ }\r
+ else if ( (mcause & MCAUSE_INT) && ((mcause & MCAUSE_CAUSE) == IRQ_M_SOFT))\r
+ {\r
+ handle_m_soft_interrupt();\r
+ }\r
+ else\r
+ {\r
+#ifndef NDEBUG\r
+ /*\r
+ Arguments supplied to this function are mcause, mepc (exception PC) and stack pointer\r
+ based onprivileged-isa specification\r
+ mcause values and meanings are:\r
+ 0 Instruction address misaligned (mtval/mbadaddr is the address)\r
+ 1 Instruction access fault (mtval/mbadaddr is the address)\r
+ 2 Illegal instruction (mtval/mbadaddr contains the offending instruction opcode)\r
+ 3 Breakpoint\r
+ 4 Load address misaligned (mtval/mbadaddr is the address)\r
+ 5 Load address fault (mtval/mbadaddr is the address)\r
+ 6 Store/AMO address fault (mtval/mbadaddr is the address)\r
+ 7 Store/AMO access fault (mtval/mbadaddr is the address)\r
+ 8 Environment call from U-mode\r
+ 9 Environment call from S-mode\r
+ A Environment call from M-mode\r
+ B Instruction page fault\r
+ C Load page fault (mtval/mbadaddr is the address)\r
+ E Store page fault (mtval/mbadaddr is the address)\r
+ */\r
+\r
+ uintptr_t mip = read_csr(mip); /* interrupt pending */\r
+ uintptr_t mbadaddr = read_csr(mbadaddr); /* additional info and meaning depends on mcause */\r
+ uintptr_t mtvec = read_csr(mtvec); /* trap vector */\r
+ uintptr_t mscratch = read_csr(mscratch); /* temporary, sometimes might hold temporary value of a0 */\r
+ uintptr_t mstatus = read_csr(mstatus); /* status contains many smaller fields: */\r
+\r
+ /* breakpoint*/\r
+ __asm("ebreak");\r
+#else\r
+ _exit(1 + mcause);\r
+#endif\r
+ }\r
+ return mepc;\r
+}\r
+\r
+#ifdef __cplusplus\r
+}\r
+#endif\r
--- /dev/null
+/*******************************************************************************\r
+ * (c) Copyright 2016-2018 Microsemi SoC Products Group. All rights reserved.\r
+ *\r
+ * @file riscv_hal.h\r
+ * @author Microsemi SoC Products Group\r
+ * @brief Hardware Abstraction Layer functions for Mi-V soft processors\r
+ *\r
+ * SVN $Revision: 9835 $\r
+ * SVN $Date: 2018-03-19 19:11:35 +0530 (Mon, 19 Mar 2018) $\r
+ */\r
+\r
+#ifndef RISCV_HAL_H\r
+#define RISCV_HAL_H\r
+\r
+#include "riscv_plic.h"\r
+\r
+#ifdef __cplusplus\r
+extern "C" {\r
+#endif\r
+\r
+/*\r
+ *Return value from External IRQ handler. This will be used to disable the External\r
+ *interrupt.\r
+ */\r
+#define EXT_IRQ_KEEP_ENABLED 0U\r
+#define EXT_IRQ_DISABLE 1U\r
+\r
+/*------------------------------------------------------------------------------\r
+ * Interrupt enable/disable.\r
+ */\r
+void __disable_irq(void);\r
+void __enable_irq(void);\r
+\r
+/*------------------------------------------------------------------------------\r
+ * System tick handler. This is generated from the RISC-V machine timer.\r
+ */\r
+void SysTick_Handler(void);\r
+\r
+/*------------------------------------------------------------------------------\r
+ * System tick configuration.\r
+ * Configures the machine timer to generate a system tick interrupt at regular\r
+ * intervals.\r
+ * Takes the number of system clock ticks between interrupts.\r
+ *\r
+ * Returns 0 if successful.\r
+ * Returns 1 if the interrupt interval cannot be achieved.\r
+ */\r
+uint32_t SysTick_Config(uint32_t ticks);\r
+\r
+#ifdef __cplusplus\r
+}\r
+#endif\r
+\r
+#endif /* RISCV_HAL_H */\r
+\r
--- /dev/null
+/*******************************************************************************\r
+ * (c) Copyright 2016-2018 Microsemi SoC Products Group. All rights reserved.\r
+ *\r
+ * @file riscv_hal_stubs.c\r
+ * @author Microsemi SoC Products Group\r
+ * @brief Mi-V soft processor Interrupt Function stubs.\r
+ * The functions below will only be linked with the application code if the user\r
+ * does not provide an implementation for these functions. These functions are\r
+ * defined with weak linking so that they can be overridden by a function with\r
+ * same prototype in the user's application code.\r
+ *\r
+ * SVN $Revision: 9835 $\r
+ * SVN $Date: 2018-03-19 19:11:35 +0530 (Mon, 19 Mar 2018) $\r
+ */\r
+#include <unistd.h>\r
+\r
+#ifdef __cplusplus\r
+extern "C" {\r
+#endif\r
+\r
+/*Weakly linked handler. Will be replaced with user's definition if provided*/\r
+__attribute__((weak)) void Software_IRQHandler(void)\r
+{\r
+ _exit(10);\r
+}\r
+\r
+/*Weakly linked handler. Will be replaced with user's definition if provided*/\r
+__attribute__((weak)) void SysTick_Handler(void)\r
+{\r
+ /*Default handler*/\r
+}\r
+\r
+/*Weakly linked handler. Will be replaced with user's definition if provided*/\r
+__attribute__((weak)) uint8_t Invalid_IRQHandler(void)\r
+{\r
+ return(0U); /*Default handler*/\r
+}\r
+\r
+/*Weakly linked handler. Will be replaced with user's definition if provided*/\r
+__attribute__((weak)) uint8_t External_1_IRQHandler(void)\r
+{\r
+ return(0U); /*Default handler*/\r
+}\r
+\r
+/*Weakly linked handler. Will be replaced with user's definition if provided*/\r
+__attribute__((weak)) uint8_t External_2_IRQHandler(void)\r
+{\r
+ return(0U); /*Default handler*/\r
+}\r
+\r
+/*Weakly linked handler. Will be replaced with user's definition if provided*/\r
+__attribute__((weak)) uint8_t External_3_IRQHandler(void)\r
+{\r
+ return(0U); /*Default handler*/\r
+}\r
+\r
+/*Weakly linked handler. Will be replaced with user's definition if provided*/\r
+__attribute__((weak)) uint8_t External_4_IRQHandler(void)\r
+{\r
+ return(0U); /*Default handler*/\r
+}\r
+\r
+/*Weakly linked handler. Will be replaced with user's definition if provided*/\r
+__attribute__((weak)) uint8_t External_5_IRQHandler(void)\r
+{\r
+ return(0U); /*Default handler*/\r
+}\r
+\r
+/*Weakly linked handler. Will be replaced with user's definition if provided*/\r
+__attribute__((weak)) uint8_t External_6_IRQHandler(void)\r
+{\r
+ return(0U); /*Default handler*/\r
+}\r
+\r
+/*Weakly linked handler. Will be replaced with user's definition if provided*/\r
+__attribute__((weak)) uint8_t External_7_IRQHandler(void)\r
+{\r
+ return(0U); /*Default handler*/\r
+}\r
+\r
+/*Weakly linked handler. Will be replaced with user's definition if provided*/\r
+__attribute__((weak)) uint8_t External_8_IRQHandler(void)\r
+{\r
+ return(0U); /*Default handler*/\r
+}\r
+\r
+/*Weakly linked handler. Will be replaced with user's definition if provided*/\r
+__attribute__((weak)) uint8_t External_9_IRQHandler(void)\r
+{\r
+ return(0U); /*Default handler*/\r
+}\r
+\r
+/*Weakly linked handler. Will be replaced with user's definition if provided*/\r
+__attribute__((weak)) uint8_t External_10_IRQHandler(void)\r
+{\r
+ return(0U); /*Default handler*/\r
+}\r
+\r
+/*Weakly linked handler. Will be replaced with user's definition if provided*/\r
+__attribute__((weak)) uint8_t External_11_IRQHandler(void)\r
+{\r
+ return(0U); /*Default handler*/\r
+}\r
+\r
+/*Weakly linked handler. Will be replaced with user's definition if provided*/\r
+__attribute__((weak)) uint8_t External_12_IRQHandler(void)\r
+{\r
+ return(0U); /*Default handler*/\r
+}\r
+\r
+/*Weakly linked handler. Will be replaced with user's definition if provided*/\r
+__attribute__((weak)) uint8_t External_13_IRQHandler(void)\r
+{\r
+ return(0U); /*Default handler*/\r
+}\r
+\r
+/*Weakly linked handler. Will be replaced with user's definition if provided*/\r
+__attribute__((weak)) uint8_t External_14_IRQHandler(void)\r
+{\r
+ return(0U); /*Default handler*/\r
+}\r
+\r
+/*Weakly linked handler. Will be replaced with user's definition if provided*/\r
+__attribute__((weak)) uint8_t External_15_IRQHandler(void)\r
+{\r
+ return(0U); /*Default handler*/\r
+}\r
+\r
+/*Weakly linked handler. Will be replaced with user's definition if provided*/\r
+__attribute__((weak)) uint8_t External_16_IRQHandler(void)\r
+{\r
+ return(0U); /*Default handler*/\r
+}\r
+\r
+/*Weakly linked handler. Will be replaced with user's definition if provided*/\r
+__attribute__((weak)) uint8_t External_17_IRQHandler(void)\r
+{\r
+ return(0U); /*Default handler*/\r
+}\r
+\r
+/*Weakly linked handler. Will be replaced with user's definition if provided*/\r
+__attribute__((weak)) uint8_t External_18_IRQHandler(void)\r
+{\r
+ return(0U); /*Default handler*/\r
+}\r
+\r
+/*Weakly linked handler. Will be replaced with user's definition if provided*/\r
+__attribute__((weak)) uint8_t External_19_IRQHandler(void)\r
+{\r
+ return(0U); /*Default handler*/\r
+}\r
+\r
+/*Weakly linked handler. Will be replaced with user's definition if provided*/\r
+__attribute__((weak)) uint8_t External_20_IRQHandler(void)\r
+{\r
+ return(0U); /*Default handler*/\r
+}\r
+\r
+/*Weakly linked handler. Will be replaced with user's definition if provided*/\r
+__attribute__((weak)) uint8_t External_21_IRQHandler(void)\r
+{\r
+ return(0U); /*Default handler*/\r
+}\r
+\r
+/*Weakly linked handler. Will be replaced with user's definition if provided*/\r
+__attribute__((weak)) uint8_t External_22_IRQHandler(void)\r
+{\r
+ return(0U); /*Default handler*/\r
+}\r
+\r
+/*Weakly linked handler. Will be replaced with user's definition if provided*/\r
+__attribute__((weak)) uint8_t External_23_IRQHandler(void)\r
+{\r
+ return(0U); /*Default handler*/\r
+}\r
+\r
+/*Weakly linked handler. Will be replaced with user's definition if provided*/\r
+__attribute__((weak)) uint8_t External_24_IRQHandler(void)\r
+{\r
+ return(0U); /*Default handler*/\r
+}\r
+\r
+/*Weakly linked handler. Will be replaced with user's definition if provided*/\r
+__attribute__((weak)) uint8_t External_25_IRQHandler(void)\r
+{\r
+ return(0U); /*Default handler*/\r
+}\r
+\r
+/*Weakly linked handler. Will be replaced with user's definition if provided*/\r
+__attribute__((weak)) uint8_t External_26_IRQHandler(void)\r
+{\r
+ return(0U); /*Default handler*/\r
+}\r
+\r
+/*Weakly linked handler. Will be replaced with user's definition if provided*/\r
+__attribute__((weak)) uint8_t External_27_IRQHandler(void)\r
+{\r
+ return(0U); /*Default handler*/\r
+}\r
+\r
+/*Weakly linked handler. Will be replaced with user's definition if provided*/\r
+__attribute__((weak)) uint8_t External_28_IRQHandler(void)\r
+{\r
+ return(0U); /*Default handler*/\r
+}\r
+\r
+/*Weakly linked handler. Will be replaced with user's definition if provided*/\r
+__attribute__((weak)) uint8_t External_29_IRQHandler(void)\r
+{\r
+ return(0U); /*Default handler*/\r
+}\r
+\r
+/*Weakly linked handler. Will be replaced with user's definition if provided*/\r
+__attribute__((weak)) uint8_t External_30_IRQHandler(void)\r
+{\r
+ return(0U); /*Default handler*/\r
+}\r
+\r
+/*Weakly linked handler. Will be replaced with user's definition if provide*/\r
+__attribute__((weak)) uint8_t External_31_IRQHandler(void)\r
+{\r
+ return(0U); /*Default handler*/\r
+}\r
+\r
+#ifdef __cplusplus\r
+}\r
+#endif\r
--- /dev/null
+/*******************************************************************************\r
+ * (c) Copyright 2016-2018 Microsemi SoC Products Group. All rights reserved.\r
+ *\r
+ * @file riscv_plic.h\r
+ * @author Microsemi SoC Products Group\r
+ * @brief Mi-V soft processor PLIC and PRCI access data structures and functions.\r
+ *\r
+ * SVN $Revision: 9838 $\r
+ * SVN $Date: 2018-03-19 19:22:54 +0530 (Mon, 19 Mar 2018) $\r
+ */\r
+#ifndef RISCV_PLIC_H\r
+#define RISCV_PLIC_H\r
+\r
+#include <stdint.h>\r
+\r
+#include "encoding.h"\r
+\r
+#ifdef __cplusplus\r
+extern "C" {\r
+#endif\r
+\r
+#define PLIC_NUM_SOURCES 31\r
+#define PLIC_NUM_PRIORITIES 0\r
+\r
+/*==============================================================================\r
+ * Interrupt numbers:\r
+ */\r
+typedef enum\r
+{\r
+ NoInterrupt_IRQn = 0,\r
+ External_1_IRQn = 1,\r
+ External_2_IRQn = 2,\r
+ External_3_IRQn = 3, \r
+ External_4_IRQn = 4,\r
+ External_5_IRQn = 5,\r
+ External_6_IRQn = 6,\r
+ External_7_IRQn = 7,\r
+ External_8_IRQn = 8,\r
+ External_9_IRQn = 9,\r
+ External_10_IRQn = 10,\r
+ External_11_IRQn = 11,\r
+ External_12_IRQn = 12,\r
+ External_13_IRQn = 13,\r
+ External_14_IRQn = 14,\r
+ External_15_IRQn = 15,\r
+ External_16_IRQn = 16,\r
+ External_17_IRQn = 17,\r
+ External_18_IRQn = 18,\r
+ External_19_IRQn = 19,\r
+ External_20_IRQn = 20,\r
+ External_21_IRQn = 21,\r
+ External_22_IRQn = 22,\r
+ External_23_IRQn = 23,\r
+ External_24_IRQn = 24,\r
+ External_25_IRQn = 25,\r
+ External_26_IRQn = 26,\r
+ External_27_IRQn = 27,\r
+ External_28_IRQn = 28,\r
+ External_29_IRQn = 29,\r
+ External_30_IRQn = 30,\r
+ External_31_IRQn = 31\r
+} IRQn_Type;\r
+\r
+\r
+/*==============================================================================\r
+ * PLIC: Platform Level Interrupt Controller\r
+ */\r
+#define PLIC_BASE_ADDR 0x40000000UL\r
+\r
+typedef struct\r
+{\r
+ volatile uint32_t PRIORITY_THRESHOLD;\r
+ volatile uint32_t CLAIM_COMPLETE;\r
+ volatile uint32_t reserved[1022];\r
+} IRQ_Target_Type;\r
+\r
+typedef struct\r
+{\r
+ volatile uint32_t ENABLES[32];\r
+} Target_Enables_Type;\r
+\r
+typedef struct\r
+{\r
+ /*-------------------- Source Priority --------------------*/\r
+ volatile uint32_t SOURCE_PRIORITY[1024];\r
+ \r
+ /*-------------------- Pending array --------------------*/\r
+ volatile const uint32_t PENDING_ARRAY[32];\r
+ volatile uint32_t RESERVED1[992];\r
+ \r
+ /*-------------------- Target enables --------------------*/\r
+ volatile Target_Enables_Type TARGET_ENABLES[15808];\r
+\r
+ volatile uint32_t RESERVED2[16384];\r
+ \r
+ /*--- Target Priority threshold and claim/complete---------*/\r
+ IRQ_Target_Type TARGET[15872];\r
+ \r
+} PLIC_Type;\r
+\r
+\r
+#define PLIC ((PLIC_Type *)PLIC_BASE_ADDR)\r
+\r
+/*==============================================================================\r
+ * PRCI: Power, Reset, Clock, Interrupt\r
+ */\r
+#define PRCI_BASE 0x44000000UL\r
+\r
+typedef struct\r
+{\r
+ volatile uint32_t MSIP[4095];\r
+ volatile uint32_t reserved;\r
+ volatile uint64_t MTIMECMP[4095];\r
+ volatile const uint64_t MTIME;\r
+} PRCI_Type;\r
+\r
+#define PRCI ((PRCI_Type *)PRCI_BASE) \r
+\r
+/*==============================================================================\r
+ * The function PLIC_init() initializes the PLIC controller and enables the \r
+ * global external interrupt bit.\r
+ */\r
+static inline void PLIC_init(void)\r
+{\r
+ uint32_t inc;\r
+ unsigned long hart_id = read_csr(mhartid);\r
+\r
+ /* Disable all interrupts for the current hart. */\r
+ for(inc = 0; inc < ((PLIC_NUM_SOURCES + 32u) / 32u); ++inc)\r
+ {\r
+ PLIC->TARGET_ENABLES[hart_id].ENABLES[inc] = 0;\r
+ }\r
+\r
+ /* Set priorities to zero. */\r
+ /* Should this really be done??? Calling PLIC_init() on one hart will cause\r
+ * the priorities previously set by other harts to be messed up. */\r
+ for(inc = 0; inc < PLIC_NUM_SOURCES; ++inc)\r
+ {\r
+ PLIC->SOURCE_PRIORITY[inc] = 0;\r
+ }\r
+\r
+ /* Set the threshold to zero. */\r
+ PLIC->TARGET[hart_id].PRIORITY_THRESHOLD = 0;\r
+\r
+ /* Enable machine external interrupts. */\r
+ set_csr(mie, MIP_MEIP);\r
+}\r
+\r
+/*==============================================================================\r
+ * The function PLIC_EnableIRQ() enables the external interrupt for the interrupt\r
+ * number indicated by the parameter IRQn.\r
+ */\r
+static inline void PLIC_EnableIRQ(IRQn_Type IRQn)\r
+{\r
+ unsigned long hart_id = read_csr(mhartid);\r
+ uint32_t current = PLIC->TARGET_ENABLES[hart_id].ENABLES[IRQn / 32];\r
+ current |= (uint32_t)1 << (IRQn % 32);\r
+ PLIC->TARGET_ENABLES[hart_id].ENABLES[IRQn / 32] = current;\r
+}\r
+\r
+/*==============================================================================\r
+ * The function PLIC_DisableIRQ() disables the external interrupt for the interrupt\r
+ * number indicated by the parameter IRQn.\r
+\r
+ * NOTE:\r
+ * This function can be used to disable the external interrupt from outside\r
+ * external interrupt handler function.\r
+ * This function MUST NOT be used from within the External Interrupt handler.\r
+ * If you wish to disable the external interrupt while the interrupt handler\r
+ * for that external interrupt is executing then you must use the return value\r
+ * EXT_IRQ_DISABLE to return from the extern interrupt handler.\r
+ */\r
+static inline void PLIC_DisableIRQ(IRQn_Type IRQn)\r
+{\r
+ unsigned long hart_id = read_csr(mhartid);\r
+ uint32_t current = PLIC->TARGET_ENABLES[hart_id].ENABLES[IRQn / 32];\r
+\r
+ current &= ~((uint32_t)1 << (IRQn % 32));\r
+\r
+ PLIC->TARGET_ENABLES[hart_id].ENABLES[IRQn / 32] = current;\r
+}\r
+\r
+/*==============================================================================\r
+ * The function PLIC_SetPriority() sets the priority for the external interrupt \r
+ * for the interrupt number indicated by the parameter IRQn.\r
+ */\r
+static inline void PLIC_SetPriority(IRQn_Type IRQn, uint32_t priority) \r
+{\r
+ PLIC->SOURCE_PRIORITY[IRQn] = priority;\r
+}\r
+\r
+/*==============================================================================\r
+ * The function PLIC_GetPriority() returns the priority for the external interrupt \r
+ * for the interrupt number indicated by the parameter IRQn.\r
+ */\r
+static inline uint32_t PLIC_GetPriority(IRQn_Type IRQn)\r
+{\r
+ return PLIC->SOURCE_PRIORITY[IRQn];\r
+}\r
+\r
+/*==============================================================================\r
+ * The function PLIC_ClaimIRQ() claims the interrupt from the PLIC controller.\r
+ */\r
+static inline uint32_t PLIC_ClaimIRQ(void)\r
+{\r
+ unsigned long hart_id = read_csr(mhartid);\r
+\r
+ return PLIC->TARGET[hart_id].CLAIM_COMPLETE;\r
+}\r
+\r
+/*==============================================================================\r
+ * The function PLIC_CompleteIRQ() indicates to the PLIC controller the interrupt\r
+ * is processed and claim is complete.\r
+ */\r
+static inline void PLIC_CompleteIRQ(uint32_t source)\r
+{\r
+ unsigned long hart_id = read_csr(mhartid);\r
+\r
+ PLIC->TARGET[hart_id].CLAIM_COMPLETE = source;\r
+}\r
+\r
+/*==============================================================================\r
+ * The function raise_soft_interrupt() raises a synchronous software interrupt by\r
+ * writing into the MSIP register.\r
+ */\r
+static inline void raise_soft_interrupt()\r
+{\r
+ unsigned long hart_id = read_csr(mhartid);\r
+\r
+ /*You need to make sure that the global interrupt is enabled*/\r
+ set_csr(mie, MIP_MSIP); /*Enable software interrupt bit */\r
+ PRCI->MSIP[hart_id] = 0x01; /*raise soft interrupt for hart0*/\r
+}\r
+\r
+/*==============================================================================\r
+ * The function clear_soft_interrupt() clears a synchronous software interrupt by\r
+ * clearing the MSIP register.\r
+ */\r
+static inline void clear_soft_interrupt()\r
+{\r
+ unsigned long hart_id = read_csr(mhartid);\r
+ PRCI->MSIP[hart_id] = 0x00; /*clear soft interrupt for hart0*/\r
+}\r
+\r
+#ifdef __cplusplus\r
+}\r
+#endif\r
+\r
+#endif /* RISCV_PLIC_H */\r
--- /dev/null
+/*******************************************************************************\r
+ * (c) Copyright 2016-2018 Microsemi Corporation. All rights reserved.\r
+ *\r
+ * Platform definitions\r
+ * Version based on requirements of RISCV-HAL\r
+ *\r
+ * SVN $Revision: 9946 $\r
+ * SVN $Date: 2018-04-30 20:26:55 +0530 (Mon, 30 Apr 2018) $\r
+ */\r
+ /*=========================================================================*//**\r
+ @mainpage Sample file detailing how hw_platform.h should be constructed for \r
+ the Mi-V processors.\r
+\r
+ @section intro_sec Introduction\r
+ The hw_platform.h is to be located in the project root directory.\r
+ Currently this file must be hand crafted when using the Mi-V Soft Processor.\r
+ \r
+ You can use this file as sample.\r
+ Rename this file from sample_hw_platform.h to hw_platform.h and store it in\r
+ the root folder of your project. Then customize it per your HW design.\r
+\r
+ @section driver_configuration Project configuration Instructions\r
+ 1. Change SYS_CLK_FREQ define to frequency of Mi-V Soft processor clock\r
+ 2 Add all other core BASE addresses\r
+ 3. Add peripheral Core Interrupt to Mi-V Soft processor interrupt mappings\r
+ 4. Define MSCC_STDIO_UART_BASE_ADDR if you want a CoreUARTapb mapped to STDIO\r
+*//*=========================================================================*/\r
+\r
+#ifndef HW_PLATFORM_H\r
+#define HW_PLATFORM_H\r
+\r
+/***************************************************************************//**\r
+ * Soft-processor clock definition\r
+ * This is the only clock brought over from the Mi-V Soft processor Libero design.\r
+ */\r
+#ifndef SYS_CLK_FREQ\r
+#define SYS_CLK_FREQ 83000000UL\r
+#endif\r
+\r
+\r
+/***************************************************************************//**\r
+ * Non-memory Peripheral base addresses\r
+ * Format of define is:\r
+ * <corename>_<instance>_BASE_ADDR\r
+ */\r
+#define COREUARTAPB0_BASE_ADDR 0x70001000UL\r
+#define COREGPIO_IN_BASE_ADDR 0x70002000UL\r
+#define CORETIMER0_BASE_ADDR 0x70003000UL\r
+#define CORETIMER1_BASE_ADDR 0x70004000UL\r
+#define COREGPIO_OUT_BASE_ADDR 0x70005000UL\r
+#define FLASH_CORE_SPI_BASE 0x70006000UL\r
+#define CORE16550_BASE_ADDR 0x70007000UL\r
+\r
+/***************************************************************************//**\r
+ * Peripheral Interrupts are mapped to the corresponding Mi-V Soft processor\r
+ * interrupt from the Libero design.\r
+ * There can be up to 31 external interrupts (IRQ[30:0] pins) on the Mi-V Soft\r
+ * processor.The Mi-V Soft processor external interrupts are defined in the\r
+ * riscv_plic.h\r
+ * These are of the form\r
+ * typedef enum\r
+{\r
+ NoInterrupt_IRQn = 0,\r
+ External_1_IRQn = 1,\r
+ External_2_IRQn = 2,\r
+ .\r
+ .\r
+ .\r
+ External_31_IRQn = 31\r
+} IRQn_Type;\r
+ \r
+ The interrupt 0 on RISC-V processor is not used. The pin IRQ[0] should map to\r
+ External_1_IRQn likewise IRQ[30] should map to External_31_IRQn\r
+ * Format of define is:\r
+ * <corename>_<instance>_<core interrupt name>\r
+ */\r
+\r
+#define TIMER0_IRQn External_30_IRQn\r
+#define TIMER1_IRQn External_31_IRQn\r
+\r
+/****************************************************************************\r
+ * Baud value to achieve a 115200 baud rate with a 83MHz system clock.\r
+ * This value is calculated using the following equation:\r
+ * BAUD_VALUE = (CLOCK / (16 * BAUD_RATE)) - 1\r
+ *****************************************************************************/\r
+#define BAUD_VALUE_115200 (SYS_CLK_FREQ / (16 * 115200)) - 1\r
+\r
+/***************************************************************************//**\r
+ * User edit section- Edit sections below if required\r
+ */\r
+#ifdef MSCC_STDIO_THRU_CORE_UART_APB\r
+/*\r
+ * A base address mapping for the STDIO printf/scanf mapping to CortUARTapb\r
+ * must be provided if it is being used\r
+ *\r
+ * e.g. #define MSCC_STDIO_UART_BASE_ADDR COREUARTAPB1_BASE_ADDR\r
+ */\r
+#define MSCC_STDIO_UART_BASE_ADDR COREUARTAPB0_BASE_ADDR\r
+\r
+#ifndef MSCC_STDIO_UART_BASE_ADDR\r
+#error MSCC_STDIO_UART_BASE_ADDR not defined- e.g. #define MSCC_STDIO_UART_BASE_ADDR COREUARTAPB1_BASE_ADDR\r
+#endif\r
+\r
+#ifndef MSCC_STDIO_BAUD_VALUE\r
+/*\r
+ * The MSCC_STDIO_BAUD_VALUE define should be set in your project's settings to\r
+ * specify the baud value used by the standard output CoreUARTapb instance for\r
+ * generating the UART's baud rate if you want a different baud rate from the\r
+ * default of 115200 baud\r
+ */\r
+#define MSCC_STDIO_BAUD_VALUE 115200\r
+#endif /*MSCC_STDIO_BAUD_VALUE*/\r
+\r
+#endif /* end of MSCC_STDIO_THRU_CORE_UART_APB */\r
+/*******************************************************************************\r
+ * End of user edit section\r
+ */\r
+#endif /* HW_PLATFORM_H */\r
+\r
+\r
--- /dev/null
+/*******************************************************************************\r
+ * (c) Copyright 2016-2018 Microsemi SoC Products Group. All rights reserved.\r
+ *\r
+ * @file syscall.c\r
+ * @author Microsemi SoC Products Group\r
+ * @brief Stubs for system calls.\r
+ *\r
+ * SVN $Revision: 9661 $\r
+ * SVN $Date: 2018-01-15 16:13:33 +0530 (Mon, 15 Jan 2018) $\r
+ */\r
+#include <stdint.h>\r
+#include <stdlib.h>\r
+#include <stddef.h>\r
+#include <unistd.h>\r
+#include <errno.h>\r
+#include <sys/stat.h>\r
+#include <sys/times.h>\r
+#include <stdio.h>\r
+#include <string.h>\r
+\r
+#include "encoding.h"\r
+\r
+#ifdef MSCC_STDIO_THRU_CORE_UART_APB\r
+\r
+#include "core_uart_apb.h"\r
+#include "hw_platform.h"\r
+\r
+#endif /*MSCC_STDIO_THRU_CORE_UART_APB*/\r
+\r
+#ifdef __cplusplus\r
+extern "C" {\r
+#endif\r
+\r
+#ifdef MSCC_STDIO_THRU_CORE_UART_APB\r
+\r
+/*------------------------------------------------------------------------------\r
+ * CoreUARTapb instance data for the CoreUARTapb instance used for standard\r
+ * output.\r
+ */\r
+static UART_instance_t g_stdio_uart;\r
+\r
+/*==============================================================================\r
+ * Flag used to indicate if the UART driver needs to be initialized.\r
+ */\r
+static int g_stdio_uart_init_done = 0;\r
+#endif /*MSCC_STDIO_THRU_CORE_UART_APB*/\r
+\r
+#undef errno\r
+int errno;\r
+\r
+char *__env[1] = { 0 };\r
+char **environ = __env;\r
+\r
+void write_hex(int fd, uint32_t hex)\r
+{\r
+ uint8_t ii;\r
+ uint8_t jj;\r
+ char towrite;\r
+ uint8_t digit;\r
+\r
+ write( fd , "0x", 2 );\r
+\r
+ for (ii = 8 ; ii > 0; ii--)\r
+ {\r
+ jj = ii-1;\r
+ digit = ((hex & (0xF << (jj*4))) >> (jj*4));\r
+ towrite = digit < 0xA ? ('0' + digit) : ('A' + (digit - 0xA));\r
+ write( fd, &towrite, 1);\r
+ }\r
+}\r
+\r
+ \r
+void _exit(int code)\r
+{\r
+#ifdef MSCC_STDIO_THRU_CORE_UART_APB\r
+ const char * message = "\nProgam has exited with code:";\r
+\r
+ write(STDERR_FILENO, message, strlen(message));\r
+ write_hex(STDERR_FILENO, code);\r
+#endif\r
+\r
+ while (1);\r
+}\r
+\r
+void *_sbrk(ptrdiff_t incr)\r
+{\r
+ extern char _end[];\r
+ extern char _heap_end[];\r
+ static char *curbrk = _end;\r
+\r
+ if ((curbrk + incr < _end) || (curbrk + incr > _heap_end))\r
+ {\r
+ return ((char *) - 1);\r
+ }\r
+\r
+ curbrk += incr;\r
+ return curbrk - incr;\r
+}\r
+\r
+int _isatty(int fd)\r
+{\r
+ if (fd == STDOUT_FILENO || fd == STDERR_FILENO)\r
+ {\r
+ return 1;\r
+ }\r
+\r
+ errno = EBADF;\r
+ return 0;\r
+}\r
+\r
+static int stub(int err)\r
+{\r
+ errno = err;\r
+ return -1;\r
+}\r
+\r
+int _open(const char* name, int flags, int mode)\r
+{\r
+ return stub(ENOENT);\r
+}\r
+\r
+int _openat(int dirfd, const char* name, int flags, int mode)\r
+{\r
+ return stub(ENOENT);\r
+}\r
+\r
+int _close(int fd)\r
+{\r
+ return stub(EBADF);\r
+}\r
+\r
+int _execve(const char* name, char* const argv[], char* const env[])\r
+{\r
+ return stub(ENOMEM);\r
+}\r
+\r
+int _fork()\r
+{\r
+ return stub(EAGAIN);\r
+}\r
+\r
+int _fstat(int fd, struct stat *st)\r
+{\r
+ if (isatty(fd))\r
+ {\r
+ st->st_mode = S_IFCHR;\r
+ return 0;\r
+ }\r
+\r
+ return stub(EBADF);\r
+}\r
+\r
+int _getpid()\r
+{\r
+ return 1;\r
+}\r
+\r
+int _kill(int pid, int sig)\r
+{\r
+ return stub(EINVAL);\r
+}\r
+\r
+int _link(const char *old_name, const char *new_name)\r
+{\r
+ return stub(EMLINK);\r
+}\r
+\r
+off_t _lseek(int fd, off_t ptr, int dir)\r
+{\r
+ if (_isatty(fd))\r
+ {\r
+ return 0;\r
+ }\r
+\r
+ return stub(EBADF);\r
+}\r
+\r
+ssize_t _read(int fd, void* ptr, size_t len)\r
+{\r
+#ifdef MSCC_STDIO_THRU_CORE_UART_APB\r
+ if (_isatty(fd))\r
+ {\r
+ /*--------------------------------------------------------------------------\r
+ * Initialize the UART driver if it is the first time this function is\r
+ * called.\r
+ */\r
+ if ( !g_stdio_uart_init_done )\r
+ {\r
+ /******************************************************************************\r
+ * Baud value:\r
+ * This value is calculated using the following equation:\r
+ * BAUD_VALUE = (CLOCK / (16 * BAUD_RATE)) - 1\r
+ *****************************************************************************/\r
+ UART_init( &g_stdio_uart, MSCC_STDIO_UART_BASE_ADDR, ((SYS_CLK_FREQ/(16 * MSCC_STDIO_BAUD_VALUE))-1), (DATA_8_BITS | NO_PARITY));\r
+ g_stdio_uart_init_done = 1;\r
+ }\r
+\r
+ return UART_get_rx(&g_stdio_uart, (uint8_t*) ptr, len);\r
+ }\r
+#endif\r
+\r
+ return stub(EBADF);\r
+}\r
+\r
+int _stat(const char* file, struct stat* st)\r
+{\r
+ return stub(EACCES);\r
+}\r
+\r
+clock_t _times(struct tms* buf)\r
+{\r
+ return stub(EACCES);\r
+}\r
+\r
+int _unlink(const char* name)\r
+{\r
+ return stub(ENOENT);\r
+}\r
+\r
+int _wait(int* status)\r
+{\r
+ return stub(ECHILD);\r
+}\r
+\r
+ssize_t _write(int fd, const void* ptr, size_t len)\r
+{\r
+\r
+#ifdef MSCC_STDIO_THRU_CORE_UART_APB\r
+ const uint8_t * current = (const uint8_t *) ptr;\r
+ size_t jj;\r
+\r
+ if (_isatty(fd))\r
+ {\r
+ /*--------------------------------------------------------------------------\r
+ * Initialize the UART driver if it is the first time this function is\r
+ * called.\r
+ */\r
+ if ( !g_stdio_uart_init_done )\r
+ {\r
+ /******************************************************************************\r
+ * Baud value:\r
+ * This value is calculated using the following equation:\r
+ * BAUD_VALUE = (CLOCK / (16 * BAUD_RATE)) - 1\r
+ *****************************************************************************/\r
+ UART_init( &g_stdio_uart, MSCC_STDIO_UART_BASE_ADDR, ((SYS_CLK_FREQ/(16 * MSCC_STDIO_BAUD_VALUE))-1), (DATA_8_BITS | NO_PARITY));\r
+ g_stdio_uart_init_done = 1;\r
+ }\r
+\r
+ for (jj = 0; jj < len; jj++)\r
+ {\r
+ UART_send(&g_stdio_uart, current + jj, 1);\r
+ if (current[jj] == '\n')\r
+ {\r
+ UART_send(&g_stdio_uart, (const uint8_t *)"\r", 1);\r
+ }\r
+ }\r
+ return len;\r
+ }\r
+#endif\r
+\r
+ return stub(EBADF);\r
+}\r
+\r
+#ifdef __cplusplus\r
+}\r
+#endif\r