diff options
author | Christian Hammacher <bmasterc@gmail.com> | 2018-05-30 15:49:59 +0300 |
---|---|---|
committer | Christian Hammacher <bmasterc@gmail.com> | 2018-05-30 15:49:59 +0300 |
commit | 59b10fb8bf6c66d0c3371fffae3ebd786664301e (patch) | |
tree | d20b0424dc3b730485c26edc5d99dbf6f5d3589d | |
parent | dbdf5476e2d2935cf16e641380e65f5ff42df69d (diff) | |
parent | bd024c6930f88aba6c0a9e25b3160fcd4d3ab67e (diff) |
Merge remote-tracking branch 'origin/v2-dev' into v2-chrishamm
42 files changed, 814 insertions, 1028 deletions
@@ -116,122 +116,6 @@ </storageModule> <storageModule moduleId="org.eclipse.cdt.core.externalSettings"/> </cconfiguration> - <cconfiguration id="cdt.managedbuild.config.gnu.cross.exe.release.516195201.976458850.241502451"> - <storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="cdt.managedbuild.config.gnu.cross.exe.release.516195201.976458850.241502451" moduleId="org.eclipse.cdt.core.settings" name="Duet2"> - <macros> - <stringMacro name="LinkFlags2" type="VALUE_TEXT" value="-Wl,--end-group -lm"/> - <stringMacro name="LinkFlags1" type="VALUE_TEXT" value="-mthumb -Wl,--cref -Wl,--check-sections -Wl,--gc-sections -Wl,--entry=Reset_Handler -Wl,--unresolved-symbols=report-all -Wl,--warn-common -Wl,--warn-section-align -Wl,--warn-unresolved-symbols -Wl,--start-group"/> - <stringMacro name="CoreName" type="VALUE_TEXT" value="CoreNG"/> - <stringMacro name="GccPath" type="VALUE_TEXT" value="/home/christian/duet-dc42/gcc-arm-none-eabi-7-2017-q4-major/bin/"/> - </macros> - <externalSettings/> - <extensions> - <extension id="org.eclipse.cdt.core.ELF" point="org.eclipse.cdt.core.BinaryParser"/> - <extension id="org.eclipse.cdt.core.GmakeErrorParser" point="org.eclipse.cdt.core.ErrorParser"/> - <extension id="org.eclipse.cdt.core.CWDLocator" point="org.eclipse.cdt.core.ErrorParser"/> - <extension id="org.eclipse.cdt.core.GCCErrorParser" point="org.eclipse.cdt.core.ErrorParser"/> - <extension id="org.eclipse.cdt.core.GASErrorParser" point="org.eclipse.cdt.core.ErrorParser"/> - <extension id="org.eclipse.cdt.core.GLDErrorParser" point="org.eclipse.cdt.core.ErrorParser"/> - </extensions> - </storageModule> - <storageModule moduleId="cdtBuildSystem" version="4.0.0"> - <configuration artifactExtension="elf" artifactName="Duet2CombinedFirmware" 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.release" cleanCommand="rm -rf" description="" id="cdt.managedbuild.config.gnu.cross.exe.release.516195201.976458850.241502451" name="Duet2" parent="cdt.managedbuild.config.gnu.cross.exe.release" postannouncebuildStep="Generating binary file" postbuildStep="arm-none-eabi-objcopy -O binary ${workspace_loc:/${ProjName}/${ConfigName}}/Duet2CombinedFirmware.elf ${workspace_loc:/${ProjName}/${ConfigName}}/Duet2CombinedFirmware.bin"> - <folderInfo id="cdt.managedbuild.config.gnu.cross.exe.release.516195201.976458850.241502451." name="/" resourcePath=""> - <toolChain id="cdt.managedbuild.toolchain.gnu.cross.exe.release.1362047835" name="Cross GCC" superClass="cdt.managedbuild.toolchain.gnu.cross.exe.release"> - <option id="cdt.managedbuild.option.gnu.cross.path.1491883811" name="Path" superClass="cdt.managedbuild.option.gnu.cross.path" useByScannerDiscovery="false" value="${GccPath}" valueType="string"/> - <option id="cdt.managedbuild.option.gnu.cross.prefix.353555591" name="Prefix" superClass="cdt.managedbuild.option.gnu.cross.prefix" useByScannerDiscovery="false" value="arm-none-eabi-" valueType="string"/> - <targetPlatform archList="all" binaryParser="org.eclipse.cdt.core.ELF" id="cdt.managedbuild.targetPlatform.gnu.cross.857793524" isAbstract="false" osList="all" superClass="cdt.managedbuild.targetPlatform.gnu.cross"/> - <builder buildPath="${workspace_loc:/RepRapFirmware}/Release" id="cdt.managedbuild.builder.gnu.cross.1026937542" keepEnvironmentInBuildfile="false" managedBuildOn="true" name="Gnu Make Builder" parallelBuildOn="true" parallelizationNumber="optimal" superClass="cdt.managedbuild.builder.gnu.cross"/> - <tool id="cdt.managedbuild.tool.gnu.cross.assembler.1415072364" name="Cross GCC Assembler" superClass="cdt.managedbuild.tool.gnu.cross.assembler"> - <inputType id="cdt.managedbuild.tool.gnu.assembler.input.769576359" superClass="cdt.managedbuild.tool.gnu.assembler.input"/> - </tool> - <tool commandLinePattern="${COMMAND} ${FLAGS} ${OUTPUT_FLAG} ${OUTPUT_PREFIX}${OUTPUT} ${INPUTS}" id="cdt.managedbuild.tool.gnu.cross.c.compiler.242253222" name="Cross GCC Compiler" superClass="cdt.managedbuild.tool.gnu.cross.c.compiler"> - <option defaultValue="gnu.c.optimization.level.most" id="gnu.c.compiler.option.optimization.level.1507087276" name="Optimization Level" superClass="gnu.c.compiler.option.optimization.level" useByScannerDiscovery="false" value="gnu.c.optimization.level.more" valueType="enumerated"/> - <option id="gnu.c.compiler.option.debugging.level.861326742" name="Debug Level" superClass="gnu.c.compiler.option.debugging.level" useByScannerDiscovery="false" value="gnu.c.debugging.level.none" valueType="enumerated"/> - <option id="gnu.c.compiler.option.misc.verbose.2125396829" name="Verbose (-v)" superClass="gnu.c.compiler.option.misc.verbose" useByScannerDiscovery="false" value="false" valueType="boolean"/> - <option id="gnu.c.compiler.option.misc.other.1007303238" name="Other flags" superClass="gnu.c.compiler.option.misc.other" useByScannerDiscovery="false" value="-c -std=gnu99 -mcpu=cortex-m4 -mthumb -mfpu=fpv4-sp-d16 -mfloat-abi=hard -ffunction-sections -fdata-sections -nostdlib -Wdouble-promotion -fsingle-precision-constant "-Wa,-ahl=$*.s"" valueType="string"/> - <option id="gnu.c.compiler.option.include.paths.1527974989" name="Include paths (-I)" superClass="gnu.c.compiler.option.include.paths" useByScannerDiscovery="false" valueType="includePath"> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/cores/arduino}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/libraries/Storage}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/asf}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/asf/common/utils}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/asf/common/services/ioport}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/asf/sam/drivers}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/asf/sam/utils}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/asf/sam/utils/cmsis/sam4e/include}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/asf/sam/utils/header_files}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/asf/sam/utils/preprocessor}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/asf/thirdparty/CMSIS/Include}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/variants/duetNG}""/> - </option> - <option id="gnu.c.compiler.option.preprocessor.def.symbols.1695995740" name="Defined symbols (-D)" superClass="gnu.c.compiler.option.preprocessor.def.symbols" useByScannerDiscovery="false" valueType="definedSymbols"> - <listOptionValue builtIn="false" value="__SAM4E8E__"/> - <listOptionValue builtIn="false" value="DUET_NG"/> - </option> - <inputType id="cdt.managedbuild.tool.gnu.c.compiler.input.763992947" superClass="cdt.managedbuild.tool.gnu.c.compiler.input"/> - </tool> - <tool id="cdt.managedbuild.tool.gnu.cross.c.linker.1561858475" name="Cross GCC Linker" superClass="cdt.managedbuild.tool.gnu.cross.c.linker"/> - <tool id="cdt.managedbuild.tool.gnu.cross.archiver.367299064" name="Cross GCC Archiver" superClass="cdt.managedbuild.tool.gnu.cross.archiver"/> - <tool command="gcc" commandLinePattern="${COMMAND} ${FLAGS} ${OUTPUT_FLAG} ${OUTPUT_PREFIX}${OUTPUT} ${LinkFlags1} "${workspace_loc:/${CoreName}/SAM4E8E/cores/arduino/syscalls.o}" ${INPUTS} ${LinkFlags2}" id="cdt.managedbuild.tool.gnu.cross.cpp.linker.2096521800" name="Cross G++ Linker" superClass="cdt.managedbuild.tool.gnu.cross.cpp.linker"> - <option id="gnu.cpp.link.option.nostdlibs.111689408" name="No startup or default libs (-nostdlib)" superClass="gnu.cpp.link.option.nostdlibs" useByScannerDiscovery="false" value="false" valueType="boolean"/> - <option id="gnu.cpp.link.option.paths.314107745" name="Library search path (-L)" superClass="gnu.cpp.link.option.paths" useByScannerDiscovery="false" valueType="libPaths"> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/SAM4E8E/}""/> - </option> - <option id="gnu.cpp.link.option.libs.698547262" name="Libraries (-l)" superClass="gnu.cpp.link.option.libs" useByScannerDiscovery="false" valueType="libs"> - <listOptionValue builtIn="false" value="${CoreName}"/> - </option> - <option id="gnu.cpp.link.option.flags.337829872" name="Linker flags" superClass="gnu.cpp.link.option.flags" useByScannerDiscovery="false" value="-Os -Wl,--gc-sections -Wl,--fatal-warnings -mcpu=cortex-m4 -mfpu=fpv4-sp-d16 -mfloat-abi=hard -T${workspace_loc:/${CoreName}/variants/duetNG/linker_scripts/gcc/flash.ld} -Wl,-Map,${workspace_loc:/${ProjName}/${ConfigName}}/${BuildArtifactFileBaseName}.map" valueType="string"/> - <inputType id="cdt.managedbuild.tool.gnu.cpp.linker.input.557435524" superClass="cdt.managedbuild.tool.gnu.cpp.linker.input"> - <additionalInput kind="additionalinputdependency" paths="$(USER_OBJS)"/> - <additionalInput kind="additionalinput" paths="$(LIBS)"/> - </inputType> - </tool> - <tool command="g++" id="cdt.managedbuild.tool.gnu.cross.cpp.compiler.1263200833" name="Cross G++ Compiler" superClass="cdt.managedbuild.tool.gnu.cross.cpp.compiler"> - <option id="gnu.cpp.compiler.option.optimization.level.402804038" name="Optimization Level" superClass="gnu.cpp.compiler.option.optimization.level" useByScannerDiscovery="false" value="gnu.cpp.compiler.optimization.level.more" valueType="enumerated"/> - <option id="gnu.cpp.compiler.option.debugging.level.919930419" name="Debug Level" superClass="gnu.cpp.compiler.option.debugging.level" useByScannerDiscovery="false" value="gnu.cpp.compiler.debugging.level.none" valueType="enumerated"/> - <option id="gnu.cpp.compiler.option.other.verbose.34932857" name="Verbose (-v)" superClass="gnu.cpp.compiler.option.other.verbose" useByScannerDiscovery="false" value="false" valueType="boolean"/> - <option id="gnu.cpp.compiler.option.other.other.549139443" name="Other flags" superClass="gnu.cpp.compiler.option.other.other" useByScannerDiscovery="false" value="-c -std=gnu++14 -mcpu=cortex-m4 -mthumb -mfpu=fpv4-sp-d16 -mfloat-abi=hard -ffunction-sections -fdata-sections -fno-threadsafe-statics -fno-rtti -fno-exceptions -nostdlib -Wdouble-promotion -fsingle-precision-constant "-Wa,-ahl=$*.s"" valueType="string"/> - <option id="gnu.cpp.compiler.option.include.paths.251815634" name="Include paths (-I)" superClass="gnu.cpp.compiler.option.include.paths" useByScannerDiscovery="false" valueType="includePath"> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/cores/arduino}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/libraries/Flash}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/libraries/SharedSpi}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/libraries/Storage}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/libraries/Wire}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/asf}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/asf/common/utils}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/asf/common/services/clock}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/asf/common/services/ioport}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/asf/sam/drivers}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/asf/sam/services/flash_efc}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/asf/sam/utils}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/asf/sam/utils/cmsis/sam4e/include}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/asf/sam/utils/header_files}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/asf/sam/utils/preprocessor}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/asf/thirdparty/CMSIS/Include}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/variants/duetNG}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${ProjName}/src}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${ProjName}/src/DuetNG}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${ProjName}/src/Networking}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/DuetWiFiSocketServer/src/include}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/FreeRTOS/src/include}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/FreeRTOS/src/portable/GCC/ARM_CM4F}""/> - </option> - <option id="gnu.cpp.compiler.option.preprocessor.def.1610427238" name="Defined symbols (-D)" superClass="gnu.cpp.compiler.option.preprocessor.def" useByScannerDiscovery="false" valueType="definedSymbols"> - <listOptionValue builtIn="false" value="__SAM4E8E__"/> - <listOptionValue builtIn="false" value="DUET_NG"/> - <listOptionValue builtIn="false" value="_XOPEN_SOURCE"/> - </option> - <inputType id="cdt.managedbuild.tool.gnu.cpp.compiler.input.151249281" superClass="cdt.managedbuild.tool.gnu.cpp.compiler.input"/> - </tool> - </toolChain> - </folderInfo> - <sourceEntries> - <entry excluding="src/Networking/LwipEthernet|src/Alligator|src/SAME70_TEST|src/Display|src/Duet|src/DuetM|src/RADDS" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name=""/> - </sourceEntries> - </configuration> - </storageModule> - <storageModule moduleId="org.eclipse.cdt.core.externalSettings"/> - </cconfiguration> <cconfiguration id="cdt.managedbuild.config.gnu.cross.exe.release.516195201.976458850.1027429289"> <storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="cdt.managedbuild.config.gnu.cross.exe.release.516195201.976458850.1027429289" moduleId="org.eclipse.cdt.core.settings" name="RADDS"> <macros> @@ -463,253 +347,6 @@ </storageModule> <storageModule moduleId="org.eclipse.cdt.core.externalSettings"/> </cconfiguration> - <cconfiguration id="cdt.managedbuild.config.gnu.cross.exe.release.516195201.976458850.241502451.1275216290.1979117592"> - <storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="cdt.managedbuild.config.gnu.cross.exe.release.516195201.976458850.241502451.1275216290.1979117592" moduleId="org.eclipse.cdt.core.settings" name="DuetM"> - <macros> - <stringMacro name="LinkFlags2" type="VALUE_TEXT" value="-Wl,--end-group -lm"/> - <stringMacro name="LinkFlags1" type="VALUE_TEXT" value="-mthumb -Wl,--cref -Wl,--check-sections -Wl,--gc-sections -Wl,--entry=Reset_Handler -Wl,--unresolved-symbols=report-all -Wl,--warn-common -Wl,--warn-section-align -Wl,--warn-unresolved-symbols -Wl,--start-group"/> - <stringMacro name="CoreName" type="VALUE_TEXT" value="CoreNG"/> - <stringMacro name="GccPath" type="VALUE_TEXT" value="/home/christian/duet-dc42/gcc-arm-none-eabi-7-2017-q4-major/bin/"/> - </macros> - <externalSettings/> - <extensions> - <extension id="org.eclipse.cdt.core.ELF" point="org.eclipse.cdt.core.BinaryParser"/> - <extension id="org.eclipse.cdt.core.GmakeErrorParser" point="org.eclipse.cdt.core.ErrorParser"/> - <extension id="org.eclipse.cdt.core.CWDLocator" point="org.eclipse.cdt.core.ErrorParser"/> - <extension id="org.eclipse.cdt.core.GCCErrorParser" point="org.eclipse.cdt.core.ErrorParser"/> - <extension id="org.eclipse.cdt.core.GASErrorParser" point="org.eclipse.cdt.core.ErrorParser"/> - <extension id="org.eclipse.cdt.core.GLDErrorParser" point="org.eclipse.cdt.core.ErrorParser"/> - </extensions> - </storageModule> - <storageModule moduleId="cdtBuildSystem" version="4.0.0"> - <configuration artifactExtension="elf" artifactName="DuetMaestroFirmware" 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.release" cleanCommand="rm -rf" description="" id="cdt.managedbuild.config.gnu.cross.exe.release.516195201.976458850.241502451.1275216290.1979117592" name="DuetM" parent="cdt.managedbuild.config.gnu.cross.exe.release" postannouncebuildStep="Generating binary file" postbuildStep="arm-none-eabi-objcopy -O binary ${workspace_loc:/${ProjName}/${ConfigName}}/DuetMaestroFirmware.elf ${workspace_loc:/${ProjName}/${ConfigName}}/DuetMaestroFirmware.bin"> - <folderInfo id="cdt.managedbuild.config.gnu.cross.exe.release.516195201.976458850.241502451.1275216290.1979117592." name="/" resourcePath=""> - <toolChain id="cdt.managedbuild.toolchain.gnu.cross.exe.release.366031386" name="Cross GCC" superClass="cdt.managedbuild.toolchain.gnu.cross.exe.release"> - <option id="cdt.managedbuild.option.gnu.cross.path.1130802612" name="Path" superClass="cdt.managedbuild.option.gnu.cross.path" useByScannerDiscovery="false" value="${GccPath}" valueType="string"/> - <option id="cdt.managedbuild.option.gnu.cross.prefix.2006501500" name="Prefix" superClass="cdt.managedbuild.option.gnu.cross.prefix" useByScannerDiscovery="false" value="arm-none-eabi-" valueType="string"/> - <targetPlatform archList="all" binaryParser="org.eclipse.cdt.core.ELF" id="cdt.managedbuild.targetPlatform.gnu.cross.703840241" isAbstract="false" osList="all" superClass="cdt.managedbuild.targetPlatform.gnu.cross"/> - <builder buildPath="${workspace_loc:/RepRapFirmware}/Release" id="cdt.managedbuild.builder.gnu.cross.891498508" keepEnvironmentInBuildfile="false" managedBuildOn="true" name="Gnu Make Builder" parallelBuildOn="true" parallelizationNumber="optimal" superClass="cdt.managedbuild.builder.gnu.cross"/> - <tool id="cdt.managedbuild.tool.gnu.cross.assembler.725393725" name="Cross GCC Assembler" superClass="cdt.managedbuild.tool.gnu.cross.assembler"> - <inputType id="cdt.managedbuild.tool.gnu.assembler.input.1095121794" superClass="cdt.managedbuild.tool.gnu.assembler.input"/> - </tool> - <tool commandLinePattern="${COMMAND} ${FLAGS} ${OUTPUT_FLAG} ${OUTPUT_PREFIX}${OUTPUT} ${INPUTS}" id="cdt.managedbuild.tool.gnu.cross.c.compiler.1499812394" name="Cross GCC Compiler" superClass="cdt.managedbuild.tool.gnu.cross.c.compiler"> - <option defaultValue="gnu.c.optimization.level.most" id="gnu.c.compiler.option.optimization.level.845554023" name="Optimization Level" superClass="gnu.c.compiler.option.optimization.level" useByScannerDiscovery="false" value="gnu.c.optimization.level.more" valueType="enumerated"/> - <option id="gnu.c.compiler.option.debugging.level.590351259" name="Debug Level" superClass="gnu.c.compiler.option.debugging.level" useByScannerDiscovery="false" value="gnu.c.debugging.level.none" valueType="enumerated"/> - <option id="gnu.c.compiler.option.misc.verbose.781620320" name="Verbose (-v)" superClass="gnu.c.compiler.option.misc.verbose" useByScannerDiscovery="false" value="false" valueType="boolean"/> - <option id="gnu.c.compiler.option.misc.other.1000778171" name="Other flags" superClass="gnu.c.compiler.option.misc.other" useByScannerDiscovery="false" value="-c -std=gnu99 -mcpu=cortex-m4 -mthumb -ffunction-sections -fdata-sections -nostdlib -Wdouble-promotion -fsingle-precision-constant "-Wa,-ahl=$*.s"" valueType="string"/> - <option id="gnu.c.compiler.option.include.paths.406147754" name="Include paths (-I)" superClass="gnu.c.compiler.option.include.paths" useByScannerDiscovery="false" valueType="includePath"> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/cores/arduino}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/libraries/Storage}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/asf}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/asf/common/utils}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/asf/common/services/ioport}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/asf/sam/drivers/hsmci}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/asf/sam/drivers/rstc}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/asf/sam/drivers/rtc}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/asf/sam/utils}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/asf/sam/utils/cmsis/sam4s/include}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/asf/sam/utils/header_files}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/asf/sam/utils/preprocessor}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/asf/thirdparty/CMSIS/Include}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/variants/sam4s}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${ProjName}/src/Networking/W5500Ethernet}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${ProjName}/src/Networking/W5500Ethernet/Wiznet/Ethernet}""/> - </option> - <option id="gnu.c.compiler.option.preprocessor.def.symbols.2086359888" name="Defined symbols (-D)" superClass="gnu.c.compiler.option.preprocessor.def.symbols" useByScannerDiscovery="false" valueType="definedSymbols"> - <listOptionValue builtIn="false" value="__SAM4S8C__"/> - <listOptionValue builtIn="false" value="DUET_M"/> - </option> - <inputType id="cdt.managedbuild.tool.gnu.c.compiler.input.1068938062" superClass="cdt.managedbuild.tool.gnu.c.compiler.input"/> - </tool> - <tool id="cdt.managedbuild.tool.gnu.cross.c.linker.1542219221" name="Cross GCC Linker" superClass="cdt.managedbuild.tool.gnu.cross.c.linker"/> - <tool id="cdt.managedbuild.tool.gnu.cross.archiver.345792883" name="Cross GCC Archiver" superClass="cdt.managedbuild.tool.gnu.cross.archiver"/> - <tool command="gcc" commandLinePattern="${COMMAND} ${FLAGS} ${OUTPUT_FLAG} ${OUTPUT_PREFIX}${OUTPUT} ${LinkFlags1} "${workspace_loc:/${CoreName}/SAM4S/cores/arduino/syscalls.o}" ${INPUTS} ${LinkFlags2}" id="cdt.managedbuild.tool.gnu.cross.cpp.linker.2089103925" name="Cross G++ Linker" superClass="cdt.managedbuild.tool.gnu.cross.cpp.linker"> - <option id="gnu.cpp.link.option.nostdlibs.137133477" name="No startup or default libs (-nostdlib)" superClass="gnu.cpp.link.option.nostdlibs" useByScannerDiscovery="false" value="false" valueType="boolean"/> - <option id="gnu.cpp.link.option.paths.857128754" name="Library search path (-L)" superClass="gnu.cpp.link.option.paths" useByScannerDiscovery="false" valueType="libPaths"> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/SAM4S/}""/> - </option> - <option id="gnu.cpp.link.option.libs.22224333" name="Libraries (-l)" superClass="gnu.cpp.link.option.libs" useByScannerDiscovery="false" valueType="libs"> - <listOptionValue builtIn="false" value="${CoreName}"/> - </option> - <option id="gnu.cpp.link.option.flags.119775687" name="Linker flags" superClass="gnu.cpp.link.option.flags" useByScannerDiscovery="false" value="-Os -Wl,--gc-sections -Wl,--fatal-warnings -mcpu=cortex-m4 -T${workspace_loc:/${CoreName}/variants/sam4s/linker_scripts/gcc/flash.ld} -Wl,-Map,${workspace_loc:/${ProjName}/${ConfigName}}/${BuildArtifactFileBaseName}.map" valueType="string"/> - <inputType id="cdt.managedbuild.tool.gnu.cpp.linker.input.2016349335" superClass="cdt.managedbuild.tool.gnu.cpp.linker.input"> - <additionalInput kind="additionalinputdependency" paths="$(USER_OBJS)"/> - <additionalInput kind="additionalinput" paths="$(LIBS)"/> - </inputType> - </tool> - <tool command="g++" id="cdt.managedbuild.tool.gnu.cross.cpp.compiler.1704683776" name="Cross G++ Compiler" superClass="cdt.managedbuild.tool.gnu.cross.cpp.compiler"> - <option id="gnu.cpp.compiler.option.optimization.level.20377069" name="Optimization Level" superClass="gnu.cpp.compiler.option.optimization.level" useByScannerDiscovery="false" value="gnu.cpp.compiler.optimization.level.more" valueType="enumerated"/> - <option id="gnu.cpp.compiler.option.debugging.level.331115034" name="Debug Level" superClass="gnu.cpp.compiler.option.debugging.level" useByScannerDiscovery="false" value="gnu.cpp.compiler.debugging.level.none" valueType="enumerated"/> - <option id="gnu.cpp.compiler.option.other.verbose.629252168" name="Verbose (-v)" superClass="gnu.cpp.compiler.option.other.verbose" useByScannerDiscovery="false" value="false" valueType="boolean"/> - <option id="gnu.cpp.compiler.option.other.other.1110817524" name="Other flags" superClass="gnu.cpp.compiler.option.other.other" useByScannerDiscovery="false" value="-c -std=gnu++14 -mcpu=cortex-m4 -mthumb -ffunction-sections -fdata-sections -fno-threadsafe-statics -fno-rtti -fno-exceptions -nostdlib -Wdouble-promotion -fsingle-precision-constant "-Wa,-ahl=$*.s"" valueType="string"/> - <option id="gnu.cpp.compiler.option.include.paths.1099513783" name="Include paths (-I)" superClass="gnu.cpp.compiler.option.include.paths" useByScannerDiscovery="false" valueType="includePath"> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/cores/arduino}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/libraries/Flash}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/libraries/SharedSpi}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/libraries/Storage}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/libraries/Wire}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/asf}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/asf/common/utils}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/asf/common/services/clock}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/asf/common/services/ioport}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/asf/sam/drivers}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/asf/sam/services/flash_efc}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/asf/sam/utils}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/asf/sam/utils/cmsis/sam4s/include}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/asf/sam/utils/header_files}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/asf/sam/utils/preprocessor}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/asf/thirdparty/CMSIS/Include}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/variants/sam4s}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${ProjName}/src}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${ProjName}/src/DuetM}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${ProjName}/src/Networking}""/> - </option> - <option id="gnu.cpp.compiler.option.preprocessor.def.1565207565" name="Defined symbols (-D)" superClass="gnu.cpp.compiler.option.preprocessor.def" useByScannerDiscovery="false" valueType="definedSymbols"> - <listOptionValue builtIn="false" value="__SAM4S8C__"/> - <listOptionValue builtIn="false" value="DUET_M"/> - <listOptionValue builtIn="false" value="_XOPEN_SOURCE"/> - </option> - <inputType id="cdt.managedbuild.tool.gnu.cpp.compiler.input.1354140799" superClass="cdt.managedbuild.tool.gnu.cpp.compiler.input"/> - </tool> - </toolChain> - </folderInfo> - <sourceEntries> - <entry excluding="src/Networking/ESP8266WiFi|src/Networking/LwipEthernet|src/DuetNG/DuetEthernet/Wiznet/Internet/TFTP|src/DuetNG/DuetEthernet/Ethernet3|src/DuetNG/DuetWiFi|src/DuetNG/DuetEthernet/Wiznet/Internet/FTPServer|src/Duet|src/DuetNG/DuetEthernet/Wiznet/Internet/SNTP|src/DuetNG/DuetEthernet/Ethernet3/examples|src/DuetNG|src/DuetNG/DuetEthernet/Wiznet/Internet/DNS|src/DuetNG/DuetEthernet/Wiznet/Application|src/DuetNG/DuetEthernet/Wiznet/Internet/MQTT|src/Alligator|src/DuetNG/DuetEthernet/Wiznet/Internet/FTPClient|src/SAME70_TEST|src/DuetNG/DuetEthernet/Wiznet/Internet/httpServer|src/DuetNG/DuetEthernet/Wiznet/Internet/SNMP|src/NetworkESP8266|src/Networking/ESP8266|src/RADDS" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name=""/> - </sourceEntries> - </configuration> - </storageModule> - <storageModule moduleId="org.eclipse.cdt.core.externalSettings"/> - </cconfiguration> - <cconfiguration id="cdt.managedbuild.config.gnu.cross.exe.release.516195201.976458850.241502451.1275216290.274082366.1645191116"> - <storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="cdt.managedbuild.config.gnu.cross.exe.release.516195201.976458850.241502451.1275216290.274082366.1645191116" moduleId="org.eclipse.cdt.core.settings" name="SAME70"> - <macros> - <stringMacro name="LinkFlags2" type="VALUE_TEXT" value="-Wl,--end-group -lm"/> - <stringMacro name="LinkFlags1" type="VALUE_TEXT" value="-mthumb -Wl,--cref -Wl,--check-sections -Wl,--gc-sections -Wl,--entry=Reset_Handler -Wl,--unresolved-symbols=report-all -Wl,--warn-common -Wl,--warn-section-align -Wl,--warn-unresolved-symbols -Wl,--start-group"/> - <stringMacro name="CoreName" type="VALUE_TEXT" value="CoreNG"/> - <stringMacro name="GccPath" type="VALUE_TEXT" value="/home/christian/duet-dc42/gcc-arm-none-eabi-7-2017-q4-major/bin/"/> - </macros> - <externalSettings/> - <extensions> - <extension id="org.eclipse.cdt.core.ELF" point="org.eclipse.cdt.core.BinaryParser"/> - <extension id="org.eclipse.cdt.core.GmakeErrorParser" point="org.eclipse.cdt.core.ErrorParser"/> - <extension id="org.eclipse.cdt.core.CWDLocator" point="org.eclipse.cdt.core.ErrorParser"/> - <extension id="org.eclipse.cdt.core.GCCErrorParser" point="org.eclipse.cdt.core.ErrorParser"/> - <extension id="org.eclipse.cdt.core.GASErrorParser" point="org.eclipse.cdt.core.ErrorParser"/> - <extension id="org.eclipse.cdt.core.GLDErrorParser" point="org.eclipse.cdt.core.ErrorParser"/> - </extensions> - </storageModule> - <storageModule moduleId="cdtBuildSystem" version="4.0.0"> - <configuration artifactExtension="elf" artifactName="SAME70Firmware" 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.release" cleanCommand="rm -rf" description="" id="cdt.managedbuild.config.gnu.cross.exe.release.516195201.976458850.241502451.1275216290.274082366.1645191116" name="SAME70" parent="cdt.managedbuild.config.gnu.cross.exe.release" postannouncebuildStep="Generating binary file" postbuildStep="arm-none-eabi-objcopy -O binary ${workspace_loc:/${ProjName}/${ConfigName}}/SAME70Firmware.elf ${workspace_loc:/${ProjName}/${ConfigName}}/SAME70Firmware.bin"> - <folderInfo id="cdt.managedbuild.config.gnu.cross.exe.release.516195201.976458850.241502451.1275216290.274082366.1645191116." name="/" resourcePath=""> - <toolChain id="cdt.managedbuild.toolchain.gnu.cross.exe.release.1208556935" name="Cross GCC" superClass="cdt.managedbuild.toolchain.gnu.cross.exe.release"> - <option id="cdt.managedbuild.option.gnu.cross.path.54036310" name="Path" superClass="cdt.managedbuild.option.gnu.cross.path" useByScannerDiscovery="false" value="${GccPath}" valueType="string"/> - <option id="cdt.managedbuild.option.gnu.cross.prefix.680180206" name="Prefix" superClass="cdt.managedbuild.option.gnu.cross.prefix" useByScannerDiscovery="false" value="arm-none-eabi-" valueType="string"/> - <targetPlatform archList="all" binaryParser="org.eclipse.cdt.core.ELF" id="cdt.managedbuild.targetPlatform.gnu.cross.245858471" isAbstract="false" osList="all" superClass="cdt.managedbuild.targetPlatform.gnu.cross"/> - <builder buildPath="${workspace_loc:/RepRapFirmware}/Release" id="cdt.managedbuild.builder.gnu.cross.1549857360" keepEnvironmentInBuildfile="false" managedBuildOn="true" name="Gnu Make Builder" parallelBuildOn="true" parallelizationNumber="optimal" superClass="cdt.managedbuild.builder.gnu.cross"/> - <tool id="cdt.managedbuild.tool.gnu.cross.assembler.51365542" name="Cross GCC Assembler" superClass="cdt.managedbuild.tool.gnu.cross.assembler"> - <inputType id="cdt.managedbuild.tool.gnu.assembler.input.930635937" superClass="cdt.managedbuild.tool.gnu.assembler.input"/> - </tool> - <tool commandLinePattern="${COMMAND} ${FLAGS} ${OUTPUT_FLAG} ${OUTPUT_PREFIX}${OUTPUT} ${INPUTS}" id="cdt.managedbuild.tool.gnu.cross.c.compiler.1860851793" name="Cross GCC Compiler" superClass="cdt.managedbuild.tool.gnu.cross.c.compiler"> - <option defaultValue="gnu.c.optimization.level.most" id="gnu.c.compiler.option.optimization.level.1218151514" name="Optimization Level" superClass="gnu.c.compiler.option.optimization.level" useByScannerDiscovery="false" value="gnu.c.optimization.level.more" valueType="enumerated"/> - <option id="gnu.c.compiler.option.debugging.level.56217404" name="Debug Level" superClass="gnu.c.compiler.option.debugging.level" useByScannerDiscovery="false" value="gnu.c.debugging.level.default" valueType="enumerated"/> - <option id="gnu.c.compiler.option.misc.verbose.625475772" name="Verbose (-v)" superClass="gnu.c.compiler.option.misc.verbose" useByScannerDiscovery="false" value="false" valueType="boolean"/> - <option id="gnu.c.compiler.option.misc.other.551649360" name="Other flags" superClass="gnu.c.compiler.option.misc.other" useByScannerDiscovery="false" value="-c -std=gnu99 -mcpu=cortex-m7 -mthumb -mfpu=fpv5-d16 -mfloat-abi=hard -ffunction-sections -fdata-sections -nostdlib -Wdouble-promotion -fsingle-precision-constant" valueType="string"/> - <option id="gnu.c.compiler.option.include.paths.279180230" name="Include paths (-I)" superClass="gnu.c.compiler.option.include.paths" useByScannerDiscovery="false" valueType="includePath"> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/cores/arduino}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/libraries/Storage}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/asf}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/asf/common/utils}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/asf/common/services/clock}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/asf/common/services/ioport}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/asf/sam/components/ethernet_phy/ksz8081rna}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/asf/sam/drivers/hsmci}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/asf/sam/drivers/gmac}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/asf/sam/drivers/pmc}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/asf/sam/drivers/rstc}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/asf/sam/drivers/rtc}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/asf/sam/utils}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/asf/sam/utils/cmsis/same70/include}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/asf/sam/utils/header_files}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/asf/sam/utils/preprocessor}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/asf/thirdparty/CMSIS/Include}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/variants/same70}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${ProjName}/src/SAME70_TEST}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${ProjName}/src/Networking/LwipEthernet}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${ProjName}/src/Networking/LwipEthernet/Lwip/src/include}""/> - </option> - <option id="gnu.c.compiler.option.preprocessor.def.symbols.1749077053" name="Defined symbols (-D)" superClass="gnu.c.compiler.option.preprocessor.def.symbols" useByScannerDiscovery="false" valueType="definedSymbols"> - <listOptionValue builtIn="false" value="__SAME70Q21__"/> - <listOptionValue builtIn="false" value="SAME70_TEST_BOARD"/> - </option> - <option id="gnu.c.compiler.option.dialect.std.699989842" name="Language standard" superClass="gnu.c.compiler.option.dialect.std" useByScannerDiscovery="true" value="gnu.c.compiler.dialect.default" valueType="enumerated"/> - <inputType id="cdt.managedbuild.tool.gnu.c.compiler.input.113093911" superClass="cdt.managedbuild.tool.gnu.c.compiler.input"/> - </tool> - <tool id="cdt.managedbuild.tool.gnu.cross.c.linker.533117704" name="Cross GCC Linker" superClass="cdt.managedbuild.tool.gnu.cross.c.linker"/> - <tool id="cdt.managedbuild.tool.gnu.cross.archiver.1081354337" name="Cross GCC Archiver" superClass="cdt.managedbuild.tool.gnu.cross.archiver"/> - <tool command="gcc" commandLinePattern="${COMMAND} ${FLAGS} ${OUTPUT_FLAG} ${OUTPUT_PREFIX}${OUTPUT} ${LinkFlags1} "${workspace_loc:/${CoreName}/SAME70/cores/arduino/syscalls.o}" ${INPUTS} ${LinkFlags2}" id="cdt.managedbuild.tool.gnu.cross.cpp.linker.910947184" name="Cross G++ Linker" superClass="cdt.managedbuild.tool.gnu.cross.cpp.linker"> - <option id="gnu.cpp.link.option.nostdlibs.1582617170" name="No startup or default libs (-nostdlib)" superClass="gnu.cpp.link.option.nostdlibs" useByScannerDiscovery="false" value="false" valueType="boolean"/> - <option id="gnu.cpp.link.option.paths.190121832" name="Library search path (-L)" superClass="gnu.cpp.link.option.paths" useByScannerDiscovery="false" valueType="libPaths"> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/SAME70/}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/FreeRTOS/SAME70}""/> - </option> - <option id="gnu.cpp.link.option.libs.1037992649" name="Libraries (-l)" superClass="gnu.cpp.link.option.libs" useByScannerDiscovery="false" valueType="libs"> - <listOptionValue builtIn="false" value="${CoreName}"/> - <listOptionValue builtIn="false" value="FreeRTOS"/> - </option> - <option id="gnu.cpp.link.option.flags.1385845561" name="Linker flags" superClass="gnu.cpp.link.option.flags" useByScannerDiscovery="false" value="-Os -Wl,--gc-sections -Wl,--fatal-warnings -mcpu=cortex-m7 -mthumb -mfpu=fpv5-d16 -mfloat-abi=hard -T${workspace_loc:/${CoreName}/variants/same70/linker_scripts/gcc/flash.ld} -Wl,-Map,${workspace_loc:/${ProjName}/${ConfigName}}/${BuildArtifactFileBaseName}.map" valueType="string"/> - <inputType id="cdt.managedbuild.tool.gnu.cpp.linker.input.557767962" superClass="cdt.managedbuild.tool.gnu.cpp.linker.input"> - <additionalInput kind="additionalinputdependency" paths="$(USER_OBJS)"/> - <additionalInput kind="additionalinput" paths="$(LIBS)"/> - </inputType> - </tool> - <tool command="g++" id="cdt.managedbuild.tool.gnu.cross.cpp.compiler.1203733011" name="Cross G++ Compiler" superClass="cdt.managedbuild.tool.gnu.cross.cpp.compiler"> - <option id="gnu.cpp.compiler.option.optimization.level.1851679280" name="Optimization Level" superClass="gnu.cpp.compiler.option.optimization.level" useByScannerDiscovery="false" value="gnu.cpp.compiler.optimization.level.more" valueType="enumerated"/> - <option id="gnu.cpp.compiler.option.debugging.level.2074037572" name="Debug Level" superClass="gnu.cpp.compiler.option.debugging.level" useByScannerDiscovery="false" value="gnu.cpp.compiler.debugging.level.default" valueType="enumerated"/> - <option id="gnu.cpp.compiler.option.other.verbose.1697711865" name="Verbose (-v)" superClass="gnu.cpp.compiler.option.other.verbose" useByScannerDiscovery="false" value="false" valueType="boolean"/> - <option id="gnu.cpp.compiler.option.other.other.930112113" name="Other flags" superClass="gnu.cpp.compiler.option.other.other" useByScannerDiscovery="false" value="-c -std=gnu++14 -mcpu=cortex-m7 -mthumb -mfpu=fpv5-d16 -mfloat-abi=hard -ffunction-sections -fdata-sections -fno-threadsafe-statics -fno-rtti -fno-exceptions -nostdlib -Wdouble-promotion -fsingle-precision-constant" valueType="string"/> - <option id="gnu.cpp.compiler.option.include.paths.2076704999" name="Include paths (-I)" superClass="gnu.cpp.compiler.option.include.paths" useByScannerDiscovery="false" valueType="includePath"> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/cores/arduino}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/libraries/Flash}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/libraries/SharedSpi}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/libraries/Storage}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/libraries/Wire}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/asf}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/asf/common/utils}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/asf/common/services/clock}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/asf/common/services/ioport}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/asf/sam/drivers}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/asf/sam/drivers/gmac}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/asf/sam/services/flash_efc}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/asf/sam/utils}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/asf/sam/utils/cmsis/same70/include}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/asf/sam/utils/header_files}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/asf/sam/utils/preprocessor}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/asf/thirdparty/CMSIS/Include}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/variants/same70}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${ProjName}/src}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${ProjName}/src/SAME70_TEST}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${ProjName}/src/Networking}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${ProjName}/src/Networking/LwipEthernet}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${ProjName}/src/Networking/LwipEthernet/Lwip/src/include}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/DuetWiFiSocketServer/src/include}""/> - </option> - <option id="gnu.cpp.compiler.option.preprocessor.def.178336065" name="Defined symbols (-D)" superClass="gnu.cpp.compiler.option.preprocessor.def" useByScannerDiscovery="false" valueType="definedSymbols"> - <listOptionValue builtIn="false" value="__SAME70Q21__"/> - <listOptionValue builtIn="false" value="SAME70_TEST_BOARD"/> - <listOptionValue builtIn="false" value="_XOPEN_SOURCE"/> - </option> - <option id="gnu.cpp.compiler.option.dialect.std.678634997" name="Language standard" superClass="gnu.cpp.compiler.option.dialect.std" useByScannerDiscovery="true" value="gnu.cpp.compiler.dialect.default" valueType="enumerated"/> - <inputType id="cdt.managedbuild.tool.gnu.cpp.compiler.input.484276272" superClass="cdt.managedbuild.tool.gnu.cpp.compiler.input"/> - </tool> - </toolChain> - </folderInfo> - <sourceEntries> - <entry excluding="src/Networking/W5500Ethernet|src/DuetNG/DuetWiFi|src/Duet|src/DuetNG/DuetEthernet/Wiznet/Internet/SNTP|src/DuetNG|src/Networking/LwipEthernet/Lwip/test|src/DuetNG/DuetEthernet/Wiznet/Internet/DNS|src/DuetNG/DuetEthernet/Wiznet/Application|src/DuetNG/DuetEthernet/Wiznet/Internet/MQTT|src/Alligator|src/Display|src/Networking/LwipEthernet/Lwip/src/apps/mqtt|src/Networking/LwipEthernet/Lwip/doc|src/DuetNG/DuetEthernet/Wiznet/Internet/TFTP|src/DuetNG/DuetEthernet/Ethernet3|src/Networking/LwipEthernet/Lwip/src/apps/snmp|src/Networking/LwipEthernet/Lwip/src/apps/httpd|src/DuetNG/DuetEthernet/Wiznet/Internet/FTPServer|src/DuetNG/DuetEthernet/Ethernet3/examples|src/Networking/LwipEthernet/Lwip/src/apps/tftp|src/Networking/LwipEthernet/Lwip/src/netif/ppp|src/Networking/LwipEthernet/Lwip/src/apps/lwiperf|src/DuetNG/DuetEthernet/Wiznet/Internet/FTPClient|src/Networking/LwipEthernet/Lwip/src/apps/sntp|src/DuetNG/DuetEthernet/Wiznet/Internet/httpServer|src/DuetNG/DuetEthernet/Wiznet/Internet/SNMP|src/DuetM|src/RADDS" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name=""/> - </sourceEntries> - </configuration> - </storageModule> - <storageModule moduleId="org.eclipse.cdt.core.externalSettings"/> - </cconfiguration> <cconfiguration id="cdt.managedbuild.config.gnu.cross.exe.release.516195201.976458850.241502451.170574622"> <storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="cdt.managedbuild.config.gnu.cross.exe.release.516195201.976458850.241502451.170574622" moduleId="org.eclipse.cdt.core.settings" name="Duet2_RTOS"> <macros> diff --git a/.settings/language.settings.xml b/.settings/language.settings.xml index b0a398db..1998c537 100644 --- a/.settings/language.settings.xml +++ b/.settings/language.settings.xml @@ -5,18 +5,7 @@ <provider copy-of="extension" id="org.eclipse.cdt.ui.UserLanguageSettingsProvider"/> <provider-reference id="org.eclipse.cdt.core.ReferencedProjectsLanguageSettingsProvider" ref="shared-provider"/> <provider-reference id="org.eclipse.cdt.managedbuilder.core.MBSLanguageSettingsProvider" ref="shared-provider"/> - <provider class="org.eclipse.cdt.internal.build.crossgcc.CrossGCCBuiltinSpecsDetector" console="false" env-hash="698946535669195332" id="org.eclipse.cdt.build.crossgcc.CrossGCCBuiltinSpecsDetector" keep-relative-paths="false" name="CDT Cross GCC Built-in Compiler Settings" parameter="${COMMAND} ${FLAGS} -E -P -v -dD "${INPUTS}"" prefer-non-shared="true"> - <language-scope id="org.eclipse.cdt.core.gcc"/> - <language-scope id="org.eclipse.cdt.core.g++"/> - </provider> - </extension> - </configuration> - <configuration id="cdt.managedbuild.config.gnu.cross.exe.release.516195201.976458850.241502451" name="Duet2"> - <extension point="org.eclipse.cdt.core.LanguageSettingsProvider"> - <provider copy-of="extension" id="org.eclipse.cdt.ui.UserLanguageSettingsProvider"/> - <provider-reference id="org.eclipse.cdt.core.ReferencedProjectsLanguageSettingsProvider" ref="shared-provider"/> - <provider-reference id="org.eclipse.cdt.managedbuilder.core.MBSLanguageSettingsProvider" ref="shared-provider"/> - <provider class="org.eclipse.cdt.internal.build.crossgcc.CrossGCCBuiltinSpecsDetector" console="false" env-hash="698946535669195332" id="org.eclipse.cdt.build.crossgcc.CrossGCCBuiltinSpecsDetector" keep-relative-paths="false" name="CDT Cross GCC Built-in Compiler Settings" parameter="${COMMAND} ${FLAGS} -E -P -v -dD "${INPUTS}"" prefer-non-shared="true"> + <provider class="org.eclipse.cdt.internal.build.crossgcc.CrossGCCBuiltinSpecsDetector" console="false" env-hash="-114279925955362495" id="org.eclipse.cdt.build.crossgcc.CrossGCCBuiltinSpecsDetector" keep-relative-paths="false" name="CDT Cross GCC Built-in Compiler Settings" parameter="${COMMAND} ${FLAGS} -E -P -v -dD "${INPUTS}"" prefer-non-shared="true"> <language-scope id="org.eclipse.cdt.core.gcc"/> <language-scope id="org.eclipse.cdt.core.g++"/> </provider> @@ -27,7 +16,7 @@ <provider copy-of="extension" id="org.eclipse.cdt.ui.UserLanguageSettingsProvider"/> <provider-reference id="org.eclipse.cdt.core.ReferencedProjectsLanguageSettingsProvider" ref="shared-provider"/> <provider-reference id="org.eclipse.cdt.managedbuilder.core.MBSLanguageSettingsProvider" ref="shared-provider"/> - <provider class="org.eclipse.cdt.internal.build.crossgcc.CrossGCCBuiltinSpecsDetector" console="false" env-hash="698946535669195332" id="org.eclipse.cdt.build.crossgcc.CrossGCCBuiltinSpecsDetector" keep-relative-paths="false" name="CDT Cross GCC Built-in Compiler Settings" parameter="${COMMAND} ${FLAGS} -E -P -v -dD "${INPUTS}"" prefer-non-shared="true"> + <provider class="org.eclipse.cdt.internal.build.crossgcc.CrossGCCBuiltinSpecsDetector" console="false" env-hash="-114279925955362495" id="org.eclipse.cdt.build.crossgcc.CrossGCCBuiltinSpecsDetector" keep-relative-paths="false" name="CDT Cross GCC Built-in Compiler Settings" parameter="${COMMAND} ${FLAGS} -E -P -v -dD "${INPUTS}"" prefer-non-shared="true"> <language-scope id="org.eclipse.cdt.core.gcc"/> <language-scope id="org.eclipse.cdt.core.g++"/> </provider> @@ -38,29 +27,7 @@ <provider copy-of="extension" id="org.eclipse.cdt.ui.UserLanguageSettingsProvider"/> <provider-reference id="org.eclipse.cdt.core.ReferencedProjectsLanguageSettingsProvider" ref="shared-provider"/> <provider-reference id="org.eclipse.cdt.managedbuilder.core.MBSLanguageSettingsProvider" ref="shared-provider"/> - <provider class="org.eclipse.cdt.internal.build.crossgcc.CrossGCCBuiltinSpecsDetector" console="false" env-hash="698946535669195332" id="org.eclipse.cdt.build.crossgcc.CrossGCCBuiltinSpecsDetector" keep-relative-paths="false" name="CDT Cross GCC Built-in Compiler Settings" parameter="${COMMAND} ${FLAGS} -E -P -v -dD "${INPUTS}"" prefer-non-shared="true"> - <language-scope id="org.eclipse.cdt.core.gcc"/> - <language-scope id="org.eclipse.cdt.core.g++"/> - </provider> - </extension> - </configuration> - <configuration id="cdt.managedbuild.config.gnu.cross.exe.release.516195201.976458850.241502451.1275216290.1979117592" name="DuetM"> - <extension point="org.eclipse.cdt.core.LanguageSettingsProvider"> - <provider copy-of="extension" id="org.eclipse.cdt.ui.UserLanguageSettingsProvider"/> - <provider-reference id="org.eclipse.cdt.core.ReferencedProjectsLanguageSettingsProvider" ref="shared-provider"/> - <provider-reference id="org.eclipse.cdt.managedbuilder.core.MBSLanguageSettingsProvider" ref="shared-provider"/> - <provider class="org.eclipse.cdt.internal.build.crossgcc.CrossGCCBuiltinSpecsDetector" console="false" env-hash="698946535669195332" id="org.eclipse.cdt.build.crossgcc.CrossGCCBuiltinSpecsDetector" keep-relative-paths="false" name="CDT Cross GCC Built-in Compiler Settings" parameter="${COMMAND} ${FLAGS} -E -P -v -dD "${INPUTS}"" prefer-non-shared="true"> - <language-scope id="org.eclipse.cdt.core.gcc"/> - <language-scope id="org.eclipse.cdt.core.g++"/> - </provider> - </extension> - </configuration> - <configuration id="cdt.managedbuild.config.gnu.cross.exe.release.516195201.976458850.241502451.1275216290.274082366.1645191116" name="SAME70"> - <extension point="org.eclipse.cdt.core.LanguageSettingsProvider"> - <provider copy-of="extension" id="org.eclipse.cdt.ui.UserLanguageSettingsProvider"/> - <provider-reference id="org.eclipse.cdt.core.ReferencedProjectsLanguageSettingsProvider" ref="shared-provider"/> - <provider-reference id="org.eclipse.cdt.managedbuilder.core.MBSLanguageSettingsProvider" ref="shared-provider"/> - <provider class="org.eclipse.cdt.internal.build.crossgcc.CrossGCCBuiltinSpecsDetector" console="false" env-hash="698946535669195332" id="org.eclipse.cdt.build.crossgcc.CrossGCCBuiltinSpecsDetector" keep-relative-paths="false" name="CDT Cross GCC Built-in Compiler Settings" parameter="${COMMAND} ${FLAGS} -E -P -v -dD "${INPUTS}"" prefer-non-shared="true"> + <provider class="org.eclipse.cdt.internal.build.crossgcc.CrossGCCBuiltinSpecsDetector" console="false" env-hash="-114279925955362495" id="org.eclipse.cdt.build.crossgcc.CrossGCCBuiltinSpecsDetector" keep-relative-paths="false" name="CDT Cross GCC Built-in Compiler Settings" parameter="${COMMAND} ${FLAGS} -E -P -v -dD "${INPUTS}"" prefer-non-shared="true"> <language-scope id="org.eclipse.cdt.core.gcc"/> <language-scope id="org.eclipse.cdt.core.g++"/> </provider> @@ -71,7 +38,7 @@ <provider copy-of="extension" id="org.eclipse.cdt.ui.UserLanguageSettingsProvider"/> <provider-reference id="org.eclipse.cdt.core.ReferencedProjectsLanguageSettingsProvider" ref="shared-provider"/> <provider-reference id="org.eclipse.cdt.managedbuilder.core.MBSLanguageSettingsProvider" ref="shared-provider"/> - <provider class="org.eclipse.cdt.internal.build.crossgcc.CrossGCCBuiltinSpecsDetector" console="false" env-hash="698946535669195332" id="org.eclipse.cdt.build.crossgcc.CrossGCCBuiltinSpecsDetector" keep-relative-paths="false" name="CDT Cross GCC Built-in Compiler Settings" parameter="${COMMAND} ${FLAGS} -E -P -v -dD "${INPUTS}"" prefer-non-shared="true"> + <provider class="org.eclipse.cdt.internal.build.crossgcc.CrossGCCBuiltinSpecsDetector" console="false" env-hash="-114279925955362495" id="org.eclipse.cdt.build.crossgcc.CrossGCCBuiltinSpecsDetector" keep-relative-paths="false" name="CDT Cross GCC Built-in Compiler Settings" parameter="${COMMAND} ${FLAGS} -E -P -v -dD "${INPUTS}"" prefer-non-shared="true"> <language-scope id="org.eclipse.cdt.core.gcc"/> <language-scope id="org.eclipse.cdt.core.g++"/> </provider> @@ -82,18 +49,7 @@ <provider copy-of="extension" id="org.eclipse.cdt.ui.UserLanguageSettingsProvider"/> <provider-reference id="org.eclipse.cdt.core.ReferencedProjectsLanguageSettingsProvider" ref="shared-provider"/> <provider-reference id="org.eclipse.cdt.managedbuilder.core.MBSLanguageSettingsProvider" ref="shared-provider"/> - <provider class="org.eclipse.cdt.internal.build.crossgcc.CrossGCCBuiltinSpecsDetector" console="false" env-hash="698946535669195332" id="org.eclipse.cdt.build.crossgcc.CrossGCCBuiltinSpecsDetector" keep-relative-paths="false" name="CDT Cross GCC Built-in Compiler Settings" parameter="${COMMAND} ${FLAGS} -E -P -v -dD "${INPUTS}"" prefer-non-shared="true"> - <language-scope id="org.eclipse.cdt.core.gcc"/> - <language-scope id="org.eclipse.cdt.core.g++"/> - </provider> - </extension> - </configuration> - <configuration id="cdt.managedbuild.config.gnu.cross.exe.release.516195201.976458850.241502451.1275216290.1979117592.1786125202" name="DuetM_RTOS"> - <extension point="org.eclipse.cdt.core.LanguageSettingsProvider"> - <provider copy-of="extension" id="org.eclipse.cdt.ui.UserLanguageSettingsProvider"/> - <provider-reference id="org.eclipse.cdt.core.ReferencedProjectsLanguageSettingsProvider" ref="shared-provider"/> - <provider-reference id="org.eclipse.cdt.managedbuilder.core.MBSLanguageSettingsProvider" ref="shared-provider"/> - <provider class="org.eclipse.cdt.internal.build.crossgcc.CrossGCCBuiltinSpecsDetector" console="false" env-hash="698946535669195332" id="org.eclipse.cdt.build.crossgcc.CrossGCCBuiltinSpecsDetector" keep-relative-paths="false" name="CDT Cross GCC Built-in Compiler Settings" parameter="${COMMAND} ${FLAGS} -E -P -v -dD "${INPUTS}"" prefer-non-shared="true"> + <provider class="org.eclipse.cdt.internal.build.crossgcc.CrossGCCBuiltinSpecsDetector" console="false" env-hash="-114279925955362495" id="org.eclipse.cdt.build.crossgcc.CrossGCCBuiltinSpecsDetector" keep-relative-paths="false" name="CDT Cross GCC Built-in Compiler Settings" parameter="${COMMAND} ${FLAGS} -E -P -v -dD "${INPUTS}"" prefer-non-shared="true"> <language-scope id="org.eclipse.cdt.core.gcc"/> <language-scope id="org.eclipse.cdt.core.g++"/> </provider> @@ -104,7 +60,7 @@ <provider copy-of="extension" id="org.eclipse.cdt.ui.UserLanguageSettingsProvider"/> <provider-reference id="org.eclipse.cdt.core.ReferencedProjectsLanguageSettingsProvider" ref="shared-provider"/> <provider-reference id="org.eclipse.cdt.managedbuilder.core.MBSLanguageSettingsProvider" ref="shared-provider"/> - <provider class="org.eclipse.cdt.internal.build.crossgcc.CrossGCCBuiltinSpecsDetector" console="false" env-hash="1552834014228" id="org.eclipse.cdt.build.crossgcc.CrossGCCBuiltinSpecsDetector" keep-relative-paths="false" name="CDT Cross GCC Built-in Compiler Settings" parameter="${COMMAND} ${FLAGS} -E -P -v -dD "${INPUTS}"" prefer-non-shared="true"> + <provider class="org.eclipse.cdt.internal.build.crossgcc.CrossGCCBuiltinSpecsDetector" console="false" env-hash="-114279925955362495" id="org.eclipse.cdt.build.crossgcc.CrossGCCBuiltinSpecsDetector" keep-relative-paths="false" name="CDT Cross GCC Built-in Compiler Settings" parameter="${COMMAND} ${FLAGS} -E -P -v -dD "${INPUTS}"" prefer-non-shared="true"> <language-scope id="org.eclipse.cdt.core.gcc"/> <language-scope id="org.eclipse.cdt.core.g++"/> </provider> diff --git a/src/BugList.txt b/src/BugList.txt index 176d30b1..41a4892b 100644 --- a/src/BugList.txt +++ b/src/BugList.txt @@ -153,7 +153,7 @@ Fixes in RC4: - [done, test] BUG extruder and additional axes don't work when doing G2/G3 moves - [done, ok] Configuring a chamber heater on H7 with no DueX5 present causes a crash -Fixes post RC4: +Fixes in RC5: - [done, ok] Connecting Internet Explorer crashes Duet due to trailing '?' - [done] spurious stall warnings when simulating - [done, test] Print monitor didn't think the print had started until a nozzle had reached target temperature @@ -162,6 +162,26 @@ Fixes post RC4: - [done] Extra axes were ignored in G2/G3 moves - [done] DWC and the Duet could deadlock if the Duet ran out of output buffers +Fixes post RC5: +- [done] M569 report includes chopper configuration register for smart drivers +- [done] If getting file info timed out it didn't close the file +- [done] DHT sensor task was running out of stack space +- [done] Correct bus conflict in DHT sensor code +- [done] Fixed unreliable DHT sensor reading in RTOS build, caused by call to micros() +- [done] Multiple DHT sensor support +- [done] Support DHT sensor on Duet Maestro +- [done] Pausing between the segments of a segmented move didn't happen even if the jerk settings were high enough +- [done - need to test filament monitors!!!] If filament monitors were deleted or the type changed, this could result in an exception +- [seems ok] Test Upload & print function, see https://forum.duet3d.com/topic/5394/new-firmware-2-0rc5-available/52 +- [done, test] When step rate limiting happens, various problems, see https://forum.duet3d.com/topic/5445/unable-to-run-128-or-256-microstepping (adjust move start time) +- [can't reproduce] Kulitorum report that first move after a pause doesn't extrude, https://forum.duet3d.com/topic/5408/does-not-extrude-first-g1-after-a-pause/7 +- [done, test] when the SD card is removed it says 1 file was invalidated even if it was more +- [done, ok] When SD card is removed during a print we get lots of internal error messages, and no "print abandoned" or similar message, also the heaters stay on +- [done] Emergency stop should turn off all spindles +- [looks like was caused by using M502] Report that filaments no longer work + +- M3 R parameter so it can restore the spinder/laser after a pause (https://forum.duet3d.com/topic/5418/cnc-laser-m3-unpause-r-parameter) +- CNC: look at G17/18/19, see https://forum.duet3d.com/topic/4669/ooznest-workbee-screw-driven - PanelDue won't connect if VIN velow minimum for stepper motors [PanelDue firmware needs to recognise status 'O'] - Add parameter to M116 to specify acceptable temperature difference - Laser support, see https://forum.duet3d.com/topic/4702/laser-cnc-support-in-rrf-gcode-semantics/4 diff --git a/src/Configuration.h b/src/Configuration.h index d843126e..3a94dfd6 100644 --- a/src/Configuration.h +++ b/src/Configuration.h @@ -113,8 +113,8 @@ constexpr unsigned int FirstMax31855ThermocoupleChannel = 100; // Temperature se constexpr unsigned int FirstMax31856ThermocoupleChannel = 150; // Temperature sensor channels 150... are MAX31856 thermocouples constexpr unsigned int FirstRtdChannel = 200; // Temperature sensor channels 200... are RTDs constexpr unsigned int FirstLinearAdcChannel = 300; // Temperature sensor channels 300... use an ADC that provides a linear output over a temperature range -constexpr unsigned int DhtTemperatureChannel = 400; // Temperature sensor channel 400 for DHTxx temperature -constexpr unsigned int DhtHumidityChannel = 401; // Temperature sensor channel 401 for DHTxx humidity +constexpr unsigned int FirstDhtTemperatureChannel = 400; // Temperature sensor channel 400 for DHTxx temperature +constexpr unsigned int FirstDhtHumidityChannel = 450; // Temperature sensor channel 401 for DHTxx humidity constexpr unsigned int FirstPT1000Channel = 500; // Temperature sensor channels 500... are PT1000 sensors connected to thermistor inputs constexpr unsigned int CpuTemperatureSenseChannel = 1000; // Sensor 1000 is the MCJU's own temperature sensor constexpr unsigned int FirstTmcDriversSenseChannel = 1001; // Sensors 1001..1002 are the TMC2660 driver temperature sense diff --git a/src/DuetM/Pins_DuetM.h b/src/DuetM/Pins_DuetM.h index 23c7dec0..50cf453a 100644 --- a/src/DuetM/Pins_DuetM.h +++ b/src/DuetM/Pins_DuetM.h @@ -32,7 +32,7 @@ constexpr size_t NumFirmwareUpdateModules = 1; // 1 module #define SUPPORT_ROLAND 0 // set nonzero to support Roland mill #define SUPPORT_SCANNER 0 // set zero to disable support for FreeLSS scanners #define SUPPORT_IOBITS 0 // set to support P parameter in G0/G1 commands -#define SUPPORT_DHT_SENSOR 0 // set nonzero to support DHT temperature/humidity sensors +#define SUPPORT_DHT_SENSOR 1 // set nonzero to support DHT temperature/humidity sensors (requires RTOS) #define SUPPORT_WORKPLACE_COORDINATES 1 // set nonzero to support G10 L2 and G53..59 #define SUPPORT_12864_LCD 1 // set nonzero to support 12864 LCD and rotary encoder diff --git a/src/DuetNG/Pins_DuetNG.h b/src/DuetNG/Pins_DuetNG.h index 22454a40..53624560 100644 --- a/src/DuetNG/Pins_DuetNG.h +++ b/src/DuetNG/Pins_DuetNG.h @@ -112,9 +112,6 @@ constexpr Pin SpiTempSensorCsPins[MaxSpiTempSensors] = { 28, 50, 51, 52, 24, 97, #endif -// DHTxx data pin -constexpr Pin DhtDataPin = 97; // Pin CS6 - // Pin that controls the ATX power on/off constexpr Pin ATX_POWER_PIN = 79; diff --git a/src/DuetNG/TMC2660.cpp b/src/DuetNG/TMC2660.cpp index 6939578c..c601fcf0 100644 --- a/src/DuetNG/TMC2660.cpp +++ b/src/DuetNG/TMC2660.cpp @@ -421,7 +421,7 @@ void TmcDriverState::SetStallDetectFilter(bool sgFilter) void TmcDriverState::SetStallMinimumStepsPerSecond(unsigned int stepsPerSecond) { - maxStallStepInterval = DDA::stepClockRate/max<unsigned int>(stepsPerSecond, 1); + maxStallStepInterval = StepClockRate/max<unsigned int>(stepsPerSecond, 1); } void TmcDriverState::SetCoolStep(uint16_t coolStepConfig) @@ -439,7 +439,7 @@ void TmcDriverState::AppendStallConfig(const StringRef& reply) const threshold -= 128; } reply.catf("stall threshold %d, filter %s, steps/sec %" PRIu32 ", coolstep %" PRIx32, - threshold, ((filtered) ? "on" : "off"), DDA::stepClockRate/maxStallStepInterval, registers[SmartEnable] & 0xFFFF); + threshold, ((filtered) ? "on" : "off"), StepClockRate/maxStallStepInterval, registers[SmartEnable] & 0xFFFF); } // Append the driver status to a string, and reset the min/max load values diff --git a/src/FilamentMonitors/Duet3DFilamentMonitor.cpp b/src/FilamentMonitors/Duet3DFilamentMonitor.cpp index e517b2b7..9b108bad 100644 --- a/src/FilamentMonitors/Duet3DFilamentMonitor.cpp +++ b/src/FilamentMonitors/Duet3DFilamentMonitor.cpp @@ -8,7 +8,7 @@ #include "Duet3DFilamentMonitor.h" #include "GCodes/GCodeBuffer.h" #include "Platform.h" -#include "Movement/DDA.h" // for stepClockRate +#include "RepRap.h" // Constructors Duet3DFilamentMonitor::Duet3DFilamentMonitor(unsigned int extruder, int type) @@ -63,7 +63,7 @@ Duet3DFilamentMonitor::PollResult Duet3DFilamentMonitor::PollReceiveBuffer(uint1 { // For the Duet3D sensors we need to decode the received data from the transition times recorded in the edgeCaptures array static constexpr uint32_t BitsPerSecond = 1000; // the nominal bit rate that the data is transmitted at - static constexpr uint32_t NominalBitLength = DDA::stepClockRate/BitsPerSecond; // the nominal bit length in step clocks + static constexpr uint32_t NominalBitLength = StepClockRate/BitsPerSecond; // the nominal bit length in step clocks static constexpr uint32_t MinBitLength = (NominalBitLength * 10)/13; // allow 30% clock speed tolerance static constexpr uint32_t MaxBitLength = (NominalBitLength * 13)/10; // allow 30% clock speed tolerance static constexpr uint32_t ErrorRecoveryDelayBits = 8; // before a start bit we want the line to be low for this long diff --git a/src/FilamentMonitors/FilamentMonitor.cpp b/src/FilamentMonitors/FilamentMonitor.cpp index 64458396..4c5254c2 100644 --- a/src/FilamentMonitors/FilamentMonitor.cpp +++ b/src/FilamentMonitors/FilamentMonitor.cpp @@ -17,14 +17,21 @@ #include "PrintMonitor.h" // Static data +Mutex FilamentMonitor::filamentSensorsMutex; FilamentMonitor *FilamentMonitor::filamentSensors[MaxExtruders] = { 0 }; // Default destructor FilamentMonitor::~FilamentMonitor() { +} + +// Call this to disable the interrupt before deleting or re-configuring a filament monitor +void FilamentMonitor::Disable() +{ if (pin != NoPin) { detachInterrupt(pin); + pin = NoPin; } } @@ -61,6 +68,59 @@ bool FilamentMonitor::ConfigurePin(GCodeBuffer& gb, const StringRef& reply, Inte return false; } +// Static initialisation +/*static*/ void FilamentMonitor::InitStatic() +{ + filamentSensorsMutex.Create(); +} + +// Handle M591 +/*static*/ GCodeResult FilamentMonitor::Configure(GCodeBuffer& gb, const StringRef& reply, unsigned int extruder) +{ + + bool seen = false; + long newSensorType; + gb.TryGetIValue('P', newSensorType, seen); + + MutexLocker lock(filamentSensorsMutex); + FilamentMonitor*& sensor = filamentSensors[extruder]; + + if (seen) + { + // We are setting the filament monitor type, so see if it has changed + if (sensor != nullptr && newSensorType != sensor->GetType()) + { + // We already have a sensor of a different type, so delete the old sensor + sensor->Disable(); + delete sensor; + sensor = nullptr; + } + + if (sensor == nullptr) + { + sensor = Create(extruder, newSensorType); // create the new sensor type, if any + } + } + + if (sensor != nullptr) + { + // Configure the sensor + const bool error = sensor->Configure(gb, reply, seen); + if (error) + { + sensor->Disable(); + delete sensor; + sensor = nullptr; + } + return GetGCodeResultFromError(error); + } + else if (!seen) + { + reply.printf("Extruder drive %u has no filament sensor", extruder); + } + return GCodeResult::ok; +} + // Factory function /*static*/ FilamentMonitor *FilamentMonitor::Create(unsigned int extruder, int type) { @@ -115,6 +175,8 @@ bool FilamentMonitor::ConfigurePin(GCodeBuffer& gb, const StringRef& reply, Inte /*static*/ void FilamentMonitor::Spin(bool full) { + MutexLocker lock(filamentSensorsMutex); + // Filament sensors for (size_t extruder = 0; extruder < MaxExtruders; ++extruder) { @@ -164,30 +226,6 @@ bool FilamentMonitor::ConfigurePin(GCodeBuffer& gb, const StringRef& reply, Inte } } -// Return the filament sensor associated with a particular extruder -/*static*/ FilamentMonitor *FilamentMonitor::GetFilamentSensor(unsigned int extruder) -{ - return (extruder < MaxExtruders) ? filamentSensors[extruder] : nullptr; -} - -// Set the filament sensor associated with a particular extruder -/*static*/ bool FilamentMonitor::SetFilamentSensorType(unsigned int extruder, int newSensorType) -{ - if (extruder < MaxExtruders) - { - FilamentMonitor*& sensor = filamentSensors[extruder]; - const int oldSensorType = (sensor == nullptr) ? 0 : sensor->GetType(); - if (newSensorType != oldSensorType) - { - delete sensor; - sensor = Create(extruder, newSensorType); - return true; - } - } - - return false; -} - // Send diagnostics info /*static*/ void FilamentMonitor::Diagnostics(MessageType mtype) { diff --git a/src/FilamentMonitors/FilamentMonitor.h b/src/FilamentMonitors/FilamentMonitor.h index 1fa4416f..1768460b 100644 --- a/src/FilamentMonitors/FilamentMonitor.h +++ b/src/FilamentMonitors/FilamentMonitor.h @@ -10,6 +10,8 @@ #include "RepRapFirmware.h" #include "MessageType.h" +#include "GCodes/GCodeResult.h" +#include "RTOSIface.h" enum class FilamentSensorStatus : uint8_t { @@ -39,23 +41,27 @@ public: // ISR for when the pin state changes. It should return true if the ISR wants the commanded extrusion to be fetched. virtual bool Interrupt() = 0; + // Call this to disable the interrupt before deleting a filament monitor + virtual void Disable(); + // Override the virtual destructor if your derived class allocates any dynamic memory virtual ~FilamentMonitor(); // Return the type of this sensor int GetType() const { return type; } + // Static initialisation + static void InitStatic(); + // Return an error message corresponding to a status code static const char *GetErrorMessage(FilamentSensorStatus f); // Poll the filament sensors static void Spin(bool full); - // Return the filament sensor associated with a particular extruder - static FilamentMonitor *GetFilamentSensor(unsigned int extruder); - - // Set the filament sensor associated with a particular extruder - static bool SetFilamentSensorType(unsigned int extruder, int newSensorType); + // Handle M591 + static GCodeResult Configure(GCodeBuffer& gb, const StringRef& reply, unsigned int extruder) + pre(extruder < MaxExtruders); // Send diagnostics info static void Diagnostics(MessageType mtype); @@ -75,6 +81,7 @@ private: static void InterruptEntry(CallbackParameter param); + static Mutex filamentSensorsMutex; static FilamentMonitor *filamentSensors[MaxExtruders]; int32_t isrExtruderStepsCommanded; diff --git a/src/FilamentMonitors/SimpleFilamentMonitor.cpp b/src/FilamentMonitors/SimpleFilamentMonitor.cpp index 5956fa71..7b0f1b57 100644 --- a/src/FilamentMonitors/SimpleFilamentMonitor.cpp +++ b/src/FilamentMonitors/SimpleFilamentMonitor.cpp @@ -8,9 +8,10 @@ #include "SimpleFilamentMonitor.h" #include "RepRap.h" #include "Platform.h" +#include "GCodes/GCodeBuffer.h" SimpleFilamentMonitor::SimpleFilamentMonitor(unsigned int extruder, int type) - : FilamentMonitor(extruder, type), highWhenNoFilament(type == 2), filamentPresent(false) + : FilamentMonitor(extruder, type), highWhenNoFilament(type == 2), filamentPresent(false), enabled(false) { } @@ -22,13 +23,20 @@ bool SimpleFilamentMonitor::Configure(GCodeBuffer& gb, const StringRef& reply, b return true; } + if (gb.Seen('S')) + { + seen = true; + enabled = (gb.GetIValue() > 0); + } + if (seen) { Check(true, false, false, 0.0); } else { - reply.printf("Simple filament sensor on endstop %d, output %s when no filament", GetEndstopNumber(), (highWhenNoFilament) ? "high" : "low"); + reply.printf("Simple filament sensor on endstop %d, %s, output %s when no filament", + GetEndstopNumber(), (enabled) ? "enabled" : "disabled", (highWhenNoFilament) ? "high" : "low"); } return false; @@ -54,14 +62,14 @@ void SimpleFilamentMonitor::Poll() FilamentSensorStatus SimpleFilamentMonitor::Check(bool full, bool hadNonPrintingMove, bool fromIsr, float filamentConsumed) { Poll(); - return (filamentPresent) ? FilamentSensorStatus::ok : FilamentSensorStatus::noFilament; + return (!enabled || filamentPresent) ? FilamentSensorStatus::ok : FilamentSensorStatus::noFilament; } // Clear the measurement state - called when we are not printing a file. Return the present/not present status if available. FilamentSensorStatus SimpleFilamentMonitor::Clear(bool full) { Poll(); - return (filamentPresent) ? FilamentSensorStatus::ok : FilamentSensorStatus::noFilament; + return (!enabled || filamentPresent) ? FilamentSensorStatus::ok : FilamentSensorStatus::noFilament; } // Print diagnostic info for this sensor diff --git a/src/FilamentMonitors/SimpleFilamentMonitor.h b/src/FilamentMonitors/SimpleFilamentMonitor.h index 25593b2b..e07f53ba 100644 --- a/src/FilamentMonitors/SimpleFilamentMonitor.h +++ b/src/FilamentMonitors/SimpleFilamentMonitor.h @@ -26,6 +26,7 @@ private: bool highWhenNoFilament; bool filamentPresent; + bool enabled; }; #endif /* SRC_FILAMENTSENSORS_SIMPLEFILAMENTMONITOR_H_ */ diff --git a/src/GCodes/GCodeInput.cpp b/src/GCodes/GCodeInput.cpp index 935143a5..35371c26 100644 --- a/src/GCodes/GCodeInput.cpp +++ b/src/GCodes/GCodeInput.cpp @@ -60,7 +60,6 @@ size_t StreamGCodeInput::BytesCached() const return device.available(); } - // Dynamic G-code input class for caching codes from software-defined sources RegularGCodeInput::RegularGCodeInput() @@ -189,15 +188,13 @@ void NetworkGCodeInput::Put(MessageType mtype, const char *buf) MutexLocker lock(bufMutex, 200); if (lock) { - if (len > BufferSpaceLeft()) + // Only cache this if we have enough space left + if (len <= BufferSpaceLeft()) { - // Don't cache this if we don't have enough space left - return; - } - - for (size_t i = 0; i < len; i++) - { - Put(mtype, buf[i]); + for (size_t i = 0; i < len; i++) + { + Put(mtype, buf[i]); + } } } } @@ -233,7 +230,7 @@ void FileGCodeInput::Reset(const FileData &file) } // Read another chunk of G-codes from the file and return true if more data is available -bool FileGCodeInput::ReadFromFile(FileData &file) +GCodeInputReadResult FileGCodeInput::ReadFromFile(FileData &file) { const size_t bytesCached = BytesCached(); @@ -264,14 +261,18 @@ bool FileGCodeInput::ReadFromFile(FileData &file) // However, unless we can use a buffer of at least 512 bytes then that is redundant, // because the data will be copied via the sector buffer in FatFS anyway. So we don't do that any more. const int bytesRead = file.Read(buffer + writingPointer, min<size_t>(BufferSpaceLeft(), GCodeInputBufferSize - writingPointer)); + if (bytesRead < 0) + { + return GCodeInputReadResult::error; + } if (bytesRead > 0) { writingPointer = (writingPointer + (size_t)bytesRead) % GCodeInputBufferSize; - return true; + return GCodeInputReadResult::haveData; } } - return bytesCached > 0; + return (bytesCached > 0) ? GCodeInputReadResult::haveData : GCodeInputReadResult::noData; } // End diff --git a/src/GCodes/GCodeInput.h b/src/GCodes/GCodeInput.h index 861ccc93..ae7ae31c 100644 --- a/src/GCodes/GCodeInput.h +++ b/src/GCodes/GCodeInput.h @@ -83,17 +83,20 @@ protected: char buffer[GCodeInputBufferSize]; }; +enum class GCodeInputReadResult : uint8_t { haveData, noData, error }; + // This class is an expansion of the RegularGCodeInput class to buffer G-codes and to rewind file positions when // nested G-code files are started. However buffered codes are not explicitly checked for M112. class FileGCodeInput : public RegularGCodeInput { public: + FileGCodeInput() : RegularGCodeInput(), lastFile(nullptr) { } void Reset() override; // This should be called when the associated file is being closed void Reset(const FileData &file); // Should be called when a specific G-code or macro file is closed or re-opened outside the reading context - bool ReadFromFile(FileData &file); // Read another chunk of G-codes from the file and return true if more data is available + GCodeInputReadResult ReadFromFile(FileData &file); // Read another chunk of G-codes from the file and return true if more data is available private: FileStore *lastFile; diff --git a/src/GCodes/GCodes.cpp b/src/GCodes/GCodes.cpp index a5790586..44bc3075 100644 --- a/src/GCodes/GCodes.cpp +++ b/src/GCodes/GCodes.cpp @@ -1416,16 +1416,21 @@ void GCodes::DoFilePrint(GCodeBuffer& gb, const StringRef& reply) FileData& fd = gb.MachineState().fileState; // Do we have more data to process? - if (fileInput->ReadFromFile(fd)) + switch (fileInput->ReadFromFile(fd)) { + case GCodeInputReadResult::haveData: // Yes - fill up the GCodeBuffer and run the next code if (fileInput->FillBuffer(&gb)) { gb.SetFinished(ActOnCode(gb, reply)); } - } - else - { + break; + + case GCodeInputReadResult::error: + AbortPrint(gb); + break; + + case GCodeInputReadResult::noData: // We have reached the end of the file. Check for the last line of gcode not ending in newline. if (!gb.StartingNewCode()) // if there is something in the buffer { @@ -1474,6 +1479,7 @@ void GCodes::DoFilePrint(GCodeBuffer& gb, const StringRef& reply) } } } + break; } } @@ -1599,20 +1605,22 @@ void GCodes::DoPause(GCodeBuffer& gb, PauseReason reason, const char *msg) ToolOffsetInverseTransform(pauseRestorePoint.moveCoords, currentUserPosition); // transform the returned coordinates to user coordinates ClearMove(); } - else if (segmentsLeft != 0 && moveBuffer.canPauseBefore) + else if (segmentsLeft != 0) { // We were not able to skip any moves, however we can skip the move that is waiting pauseRestorePoint.virtualExtruderPosition = moveBuffer.virtualExtruderPosition; pauseRestorePoint.filePos = moveBuffer.filePos; pauseRestorePoint.feedRate = moveBuffer.feedRate; + pauseRestorePoint.proportionDone = (float)(totalSegments - segmentsLeft)/(float)totalSegments; ToolOffsetInverseTransform(pauseRestorePoint.moveCoords, currentUserPosition); // transform the returned coordinates to user coordinates ClearMove(); } else { - // We were not able to skip any moves, and if there is a move waiting then we can't skip that one either + // We were not able to skip any moves, and there is no move waiting pauseRestorePoint.feedRate = fileGCode->MachineState().feedRate; pauseRestorePoint.virtualExtruderPosition = virtualExtruderPosition; + pauseRestorePoint.proportionDone = 0.0; // TODO: when using RTOS there is a possible race condition in the following, // because we might try to pause when a waiting move has just been added but before the gcode buffer has been re-initialised ready for the next command @@ -2423,6 +2431,7 @@ const char* GCodes::DoStraightMove(GCodeBuffer& gb, bool isCoordinated) doingArcMove = false; FinaliseMove(gb); + UnlockAll(gb); // allow pause return nullptr; } @@ -2590,16 +2599,16 @@ const char* GCodes::DoArcMove(GCodeBuffer& gb, bool clockwise) doingArcMove = true; FinaliseMove(gb); + UnlockAll(gb); // allow pause // debugPrintf("Radius %.2f, initial angle %.1f, increment %.1f, segments %u\n", // arcRadius, arcCurrentAngle * RadiansToDegrees, arcAngleIncrement * RadiansToDegrees, segmentsLeft); return nullptr; } -// Adjust the move parameters to account for segmentation and/or part of the move having been done already +// Adjust the move parameters to account for segmentation and/or part of the move having been done already void GCodes::FinaliseMove(GCodeBuffer& gb) { moveBuffer.canPauseAfter = (moveBuffer.endStopsToCheck == 0); - moveBuffer.canPauseBefore = true; moveBuffer.filePos = (&gb == fileGCode) ? gb.GetFilePosition(fileInput->BytesCached()) : noFilePosition; moveBuffer.virtualExtruderPosition = virtualExtruderPosition; @@ -2734,7 +2743,7 @@ void GCodes::ClearMove() // Cancel any macro or print in progress void GCodes::AbortPrint(GCodeBuffer& gb) { - gb.AbortFile(fileInput); // stop executing any files or macros that this GCodeBuffer is running + (void)gb.AbortFile(fileInput); // stop executing any files or macros that this GCodeBuffer is running if (&gb == fileGCode) // if the current command came from a file being printed { StopPrint(StopPrintReason::abort); @@ -4153,7 +4162,7 @@ GCodeResult GCodes::LoadFilament(GCodeBuffer& gb, const StringRef& reply) // Unload the current filament from a tool GCodeResult GCodes::UnloadFilament(GCodeBuffer& gb, const StringRef& reply) { - Tool *tool = reprap.GetCurrentTool(); + Tool * const tool = reprap.GetCurrentTool(); if (tool == nullptr) { reply.copy("No tool selected"); diff --git a/src/GCodes/GCodes.h b/src/GCodes/GCodes.h index 58cb449f..29190528 100644 --- a/src/GCodes/GCodes.h +++ b/src/GCodes/GCodes.h @@ -125,7 +125,6 @@ public: uint8_t isFirmwareRetraction : 1; // true if this is a firmware retraction/un-retraction move uint8_t usePressureAdvance : 1; // true if we want to us extruder pressure advance, if there is any extrusion - uint8_t canPauseBefore : 1; // true if we can pause before this move uint8_t canPauseAfter : 1; // true if we can pause just after this move and successfully restart uint8_t hasExtrusion : 1; // true if the move includes extrusion - only valid if the move was set up by SetupMove uint8_t isCoordinated : 1; // true if this is a coordinates move diff --git a/src/GCodes/GCodes2.cpp b/src/GCodes/GCodes2.cpp index 616cb4b6..7d8d78e4 100644 --- a/src/GCodes/GCodes2.cpp +++ b/src/GCodes/GCodes2.cpp @@ -3168,18 +3168,17 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, const StringRef& reply) { float timings[4]; platform.GetDriverStepTiming(drive, timings); - reply.printf("Drive %u runs %s, active %s enable," -#if HAS_SMART_DRIVERS - " mode %s," -#endif - " step timing %.1f,%.1f,%.1f,%.1f microseconds", + reply.printf("Drive %u runs %s, active %s enable, step timing %.1f:%.1f:%.1f:%.1f us", drive, (platform.GetDirectionValue(drive)) ? "forwards" : "in reverse", (platform.GetEnableValue(drive)) ? "high" : "low", + (double)timings[0], (double)timings[1], (double)timings[2], (double)timings[3]); #if HAS_SMART_DRIVERS - TranslateDriverMode(SmartDrivers::GetDriverMode(drive)), + if (drive < platform.GetNumSmartDrivers()) + { + reply.catf(", mode %s, ccr 0x%05" PRIx32, TranslateDriverMode(SmartDrivers::GetDriverMode(drive)), SmartDrivers::GetChopperControlRegister(drive)); + } #endif - (double)timings[0], (double)timings[1], (double)timings[2], (double)timings[3]); } } } @@ -3562,29 +3561,7 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, const StringRef& reply) const unsigned int extruder = gb.GetUIValue(); if (extruder < numExtruders) { - bool seen = false; - long sensorType; - gb.TryGetIValue('P', sensorType, seen); - if (seen) - { - FilamentMonitor::SetFilamentSensorType(extruder, sensorType); - } - - FilamentMonitor *sensor = FilamentMonitor::GetFilamentSensor(extruder); - if (sensor != nullptr) - { - // Configure the sensor - const bool error = sensor->Configure(gb, reply, seen); - result = GetGCodeResultFromError(error); - if (error) - { - FilamentMonitor::SetFilamentSensorType(extruder, 0); // delete the sensor - } - } - else if (!seen) - { - reply.printf("Extruder drive %u has no filament sensor", extruder); - } + result = FilamentMonitor::Configure(gb, reply, extruder); } } break; diff --git a/src/GCodes/GCodes3.cpp b/src/GCodes/GCodes3.cpp index 7ed2812a..05cd8948 100644 --- a/src/GCodes/GCodes3.cpp +++ b/src/GCodes/GCodes3.cpp @@ -757,7 +757,6 @@ GCodeResult GCodes::ProbeTool(GCodeBuffer& gb, const StringRef& reply) moveBuffer.usePressureAdvance = false; moveBuffer.filePos = noFilePosition; moveBuffer.canPauseAfter = false; - moveBuffer.canPauseBefore = true; // Decide which way and how far to go if (gb.Seen('R')) diff --git a/src/Heating/Heat.cpp b/src/Heating/Heat.cpp index 4227f0d0..d56fbb83 100644 --- a/src/Heating/Heat.cpp +++ b/src/Heating/Heat.cpp @@ -139,7 +139,7 @@ void Heat::Init() #if SUPPORT_DHT_SENSOR // Initialise static fields of the DHT sensor - DhtSensor::InitStatic(); + DhtSensorHardwareInterface::InitStatic(); #endif coldExtrude = false; diff --git a/src/Heating/Sensors/DhtSensor.cpp b/src/Heating/Sensors/DhtSensor.cpp index 1b1dad8f..016723af 100644 --- a/src/Heating/Sensors/DhtSensor.cpp +++ b/src/Heating/Sensors/DhtSensor.cpp @@ -12,101 +12,104 @@ #if SUPPORT_DHT_SENSOR -const uint32_t MinimumReadInterval = 2000; // ms -const uint32_t MaximumReadTime = 50; // ms +constexpr uint32_t MinimumReadInterval = 2000; // ms +constexpr uint32_t MaximumReadTime = 20; // ms +constexpr uint32_t MinimumOneBitLength = 50; // microseconds +constexpr uint32_t MinimumOneBitStepClocks = (StepClockRate * MinimumOneBitLength)/1000000; +# include "Tasks.h" -# ifdef RTOS - -# include "Tasks.h" - -constexpr uint32_t DhtTaskStackWords = 80; // task stack size in dwords -static Task<DhtTaskStackWords> *dhtTask; +// Static data members of class DhtSensorHardwareInterface +Mutex DhtSensorHardwareInterface::dhtMutex; +Task<DhtSensorHardwareInterface::DhtTaskStackWords> *DhtSensorHardwareInterface::dhtTask = nullptr; +DhtSensorHardwareInterface *DhtSensorHardwareInterface::activeSensors[MaxSpiTempSensors] = { 0 }; extern "C" void DhtTask(void * pvParameters) { - DhtSensor::SensorTask(); + DhtSensorHardwareInterface::SensorTask(); } -# else - -uint32_t DhtSensor::lastReadTime = 0; -DhtSensor::SensorState DhtSensor::state = Initialising; -uint32_t DhtSensor::lastOperationTime = 0; - -# endif - -size_t DhtSensor::numInstances = 0; -DhtSensorType DhtSensor::type = DhtSensorType::Dht11; -TemperatureError DhtSensor::lastResult = TemperatureError::notInitialised; -float DhtSensor::lastTemperature = BAD_ERROR_TEMPERATURE; -float DhtSensor::lastHumidity = BAD_ERROR_TEMPERATURE; -size_t DhtSensor::badTemperatureCount = 0; - -Mutex DhtSensor::dhtMutex; +// Pulse ISR +extern "C" void DhtDataTransition(CallbackParameter cp) +{ + static_cast<DhtSensorHardwareInterface*>(cp.vp)->Interrupt(); +} +DhtSensorHardwareInterface::DhtSensorHardwareInterface(Pin p_pin) + : sensorPin(p_pin), type(DhtSensorType::none), lastResult(TemperatureError::notInitialised), + lastTemperature(BAD_ERROR_TEMPERATURE), lastHumidity(BAD_ERROR_TEMPERATURE), badTemperatureCount(0) +{ +} -DhtSensor::DhtSensor(unsigned int channel) : TemperatureSensor(channel, "DHTxx") +TemperatureError DhtSensorHardwareInterface::GetTemperatureOrHumidity(float& t, bool wantHumidity) const { - numInstances++; + t = (wantHumidity) ? lastHumidity : lastTemperature; + return lastResult; } -DhtSensor::~DhtSensor() +/*static*/ GCodeResult DhtSensorHardwareInterface::Configure(TemperatureSensor *ts, unsigned int relativeChannel, unsigned int mCode, unsigned int heater, GCodeBuffer& gb, const StringRef& reply) { - numInstances--; + MutexLocker lock(dhtMutex); + + if (relativeChannel >= MaxSpiTempSensors || activeSensors[relativeChannel] == nullptr) + { + reply.copy("invalid channel"); + return GCodeResult::error; + } + + return activeSensors[relativeChannel]->Configure(ts, mCode, heater, gb, reply); } -GCodeResult DhtSensor::Configure(unsigned int mCode, unsigned int heater, GCodeBuffer& gb, const StringRef& reply) +GCodeResult DhtSensorHardwareInterface::Configure(TemperatureSensor *ts, unsigned int mCode, unsigned int heater, GCodeBuffer& gb, const StringRef& reply) { GCodeResult rslt = GCodeResult::ok; if (mCode == 305) { bool seen = false; - TryConfigureHeaterName(gb, seen); + ts->TryConfigureHeaterName(gb, seen); if (gb.Seen('T')) { - MutexLocker lock(dhtMutex); seen = true; const int dhtType = gb.GetIValue(); switch (dhtType) { - case 11: - type = DhtSensorType::Dht11; - break; - case 21: - type = DhtSensorType::Dht21; - break; - case 22: - type = DhtSensorType::Dht22; - break; - default: - reply.copy("Invalid DHT sensor type"); - rslt = GCodeResult::error; - break; + case 11: + type = DhtSensorType::Dht11; + break; + case 21: + type = DhtSensorType::Dht21; + break; + case 22: + type = DhtSensorType::Dht22; + break; + default: + reply.copy("Invalid DHT sensor type"); + rslt = GCodeResult::error; + break; } } if (!seen && !gb.Seen('X')) { - CopyBasicHeaterDetails(heater, reply); + ts->CopyBasicHeaterDetails(heater, reply); const char *sensorTypeString; switch (type) { - case DhtSensorType::Dht11: - sensorTypeString = "DHT11"; - break; - case DhtSensorType::Dht21: - sensorTypeString = "DHT21"; - break; - case DhtSensorType::Dht22: - sensorTypeString = "DHT22"; - break; - default: - sensorTypeString = "unknown"; - break; + case DhtSensorType::Dht11: + sensorTypeString = "DHT11"; + break; + case DhtSensorType::Dht21: + sensorTypeString = "DHT21"; + break; + case DhtSensorType::Dht22: + sensorTypeString = "DHT22"; + break; + default: + sensorTypeString = "unknown"; + break; } reply.catf(", sensor type %s", sensorTypeString); } @@ -114,246 +117,185 @@ GCodeResult DhtSensor::Configure(unsigned int mCode, unsigned int heater, GCodeB return rslt; } -void DhtSensor::Init() +// Create a hardware interface object re the specified channel if there isn't already +DhtSensorHardwareInterface *DhtSensorHardwareInterface::Create(unsigned int relativeChannel) { -#ifdef RTOS + if (relativeChannel >= MaxSpiTempSensors) + { + return nullptr; + } + + MutexLocker lock(dhtMutex); + + if (activeSensors[relativeChannel] == nullptr) + { + activeSensors[relativeChannel] = new DhtSensorHardwareInterface(SpiTempSensorCsPins[relativeChannel]); + } + if (dhtTask == nullptr) { dhtTask = new Task<DhtTaskStackWords>; dhtTask->Create(DhtTask, "DHTSENSOR", nullptr, TaskBase::HeatPriority); } -#endif + + return activeSensors[relativeChannel]; } -/*static*/ void DhtSensor::InitStatic() +/*static*/ void DhtSensorHardwareInterface::InitStatic() { dhtMutex.Create(); } -TemperatureError DhtSensor::GetTemperature(float& t) +/*static*/ TemperatureError DhtSensorHardwareInterface::GetTemperatureOrHumidity(unsigned int relativeChannel, float& t, bool wantHumidity) { - MutexLocker lock(dhtMutex); - switch (GetSensorChannel()) + if (relativeChannel >= MaxSpiTempSensors) { - case DhtTemperatureChannel: - t = lastTemperature; - return lastResult; - - case DhtHumidityChannel: - t = lastHumidity; - return lastResult; - - default: - return TemperatureError::unknownChannel; + t = BAD_ERROR_TEMPERATURE; + return TemperatureError::unknownChannel; } -} -// Pulse ISR -uint32_t lastPulseTime; -volatile uint8_t numPulses; -uint32_t pulses[41]; // 1 start bit + 40 data bits + MutexLocker lock(dhtMutex); -void DhtDataTransition(CallbackParameter) -{ - const uint32_t now = micros(); - if (digitalRead(DhtDataPin) == HIGH) - { - lastPulseTime = now; - } - else if (lastPulseTime > 0) + if (activeSensors[relativeChannel] == nullptr) { - pulses[numPulses++] = now - lastPulseTime; - if (numPulses == ARRAY_SIZE(pulses)) - { - detachInterrupt(DhtDataPin); - } + t = BAD_ERROR_TEMPERATURE; + return TemperatureError::notInitialised; } -} -#ifdef RTOS + return activeSensors[relativeChannel]->GetTemperatureOrHumidity(t, wantHumidity); +} -/*static*/ void DhtSensor::SensorTask() +void DhtSensorHardwareInterface::Interrupt() { - for (;;) + if (numPulses < ARRAY_SIZE(pulses)) { - // Don't do anything if the sensor is not configured - if (numInstances == 0) + const uint16_t now = Platform::GetInterruptClocks16(); + if (digitalRead(sensorPin)) { - RTOSIface::Yield(); - continue; + lastPulseTime = now; } - - // Send start signal. See DHT datasheet for full signal diagram: - // http://www.adafruit.com/datasheets/Digital%20humidity%20and%20temperature%20sensor%20AM2302.pdf - pinMode(DhtDataPin, OUTPUT_HIGH); - delay(250); - digitalWrite(DhtDataPin, LOW); - delay(20); - - // End the start signal by setting data line high for 40 microseconds - digitalWrite(DhtDataPin, HIGH); - delayMicroseconds(40); - - // Now start reading the data line to get the value from the DHT sensor - pinMode(DhtDataPin, INPUT_PULLUP); - delayMicroseconds(10); - - // Read from the DHT sensor using an ISR - numPulses = 0; - lastPulseTime = 0; - attachInterrupt(DhtDataPin, DhtDataTransition, INTERRUPT_MODE_CHANGE, nullptr); - - // Wait for the incoming signal to be read by the ISR (1 start bit + 40 data bits) - // The loop below could be replaced by a semaphore as well. - const uint32_t readStartTime = xTaskGetTickCount(); - do + else if (lastPulseTime != 0) { - // Make sure we don't time out - if (xTaskGetTickCount() - readStartTime > MaximumReadTime) + pulses[numPulses++] = now - lastPulseTime; +#if 0 + if (numPulses == ARRAY_SIZE(pulses)) { - detachInterrupt(DhtDataPin); - lastResult = TemperatureError::timeout; - break; - } - - RTOSIface::Yield(); - } - while (numPulses != ARRAY_SIZE(pulses)); - - // If that succeeded, attempt to convert the signal into temp+RH values - if (numPulses == ARRAY_SIZE(pulses)) - { - MutexLocker lock(dhtMutex); - - ProcessReadings(); - if (lastResult == TemperatureError::success || badTemperatureCount > MAX_BAD_TEMPERATURE_COUNT) - { - badTemperatureCount = 0; - } - else - { - badTemperatureCount++; - lastResult = TemperatureError::success; + vTaskNotifyGiveFromISR(dhtTask->GetHandle(), nullptr); // wake up the task } +#endif } - - // Wait a moment before starting a new measurement - delay(MinimumReadInterval); } } -#else - -// Keep this sensor running -/*static*/ void DhtSensor::Spin() +void DhtSensorHardwareInterface::TakeReading() { - if (numInstances == 0 || millis() - lastReadTime < MinimumReadInterval) - { - return; - } - - switch (state) + if (type != DhtSensorType::none) // if sensor has been configured { - case Initialising: // Send start signal. See DHT datasheet for full signal diagram: // http://www.adafruit.com/datasheets/Digital%20humidity%20and%20temperature%20sensor%20AM2302.pdf - pinMode(DhtDataPin, OUTPUT_HIGH); + pinMode(sensorPin, OUTPUT_HIGH); + delay(250); - state = Starting; - lastOperationTime = millis(); - break; + digitalWrite(sensorPin, LOW); + delay(20); - case Starting: - // Wait 250ms - if (millis() - lastOperationTime >= 250) { - digitalWrite(DhtDataPin, LOW); + TaskCriticalSectionLocker lock; // make sure the Heat task doesn't interrupt the sequence - state = Starting2; - lastOperationTime = millis(); - } - break; - - case Starting2: - // Wait 20ms - if (millis() - lastOperationTime >= 20) - { - // End the start signal by setting data line high for 40 microseconds - digitalWrite(DhtDataPin, HIGH); - delayMicroseconds(40); + // End the start signal by setting data line high. the sensor will respond with the start bit in 20 to 40us. + // We need only force the data line high long enough to charge the line capacitance, after that the pullup resistor keeps it high. + digitalWrite(sensorPin, HIGH); // this will generate an interrupt, but we will ignore it + delayMicroseconds(3); // Now start reading the data line to get the value from the DHT sensor - pinMode(DhtDataPin, INPUT_PULLUP); - delayMicroseconds(10); + pinMode(sensorPin, INPUT_PULLUP); - // Read from the DHT sensor using an ISR, because we cannot use delays - // due to the fact that this messes with the stepping ISR - numPulses = 0; + // It appears that switching the pin to an output disables the interrupt, so we need to call attachInterrupt here + // We are likely to get an immediate interrupt at this point corresponding to the low-to-high transition. We must ignore this. + numPulses = ARRAY_SIZE(pulses); // tell the ISR not to collect data yet + attachInterrupt(sensorPin, DhtDataTransition, INTERRUPT_MODE_CHANGE, this); lastPulseTime = 0; - attachInterrupt(DhtDataPin, DhtDataTransition, INTERRUPT_MODE_CHANGE, nullptr); - - // Wait for the next operation to complete - lastOperationTime = millis(); - state = Reading; + numPulses = 0; // tell the ISR to collect data } - break; - case Reading: - // Make sure we don't time out - if (millis() - lastOperationTime > MaximumReadTime) + // Wait for the incoming signal to be read by the ISR (1 start bit + 40 data bits), or until timeout. + // We don't have the ISR wake the process up, because that would require the priority of the pin change interrupt to be reduced. + // So we just delay for long enough for the data to have been sent. It takes typically 4 to 5ms. + delay(MaximumReadTime); + + detachInterrupt(sensorPin); + + // Attempt to convert the signal into temp+RH values + const TemperatureError rslt = ProcessReadings(); + if (rslt == TemperatureError::success) { - detachInterrupt(DhtDataPin); - state = Initialising; - lastReadTime = millis(); - lastResult = TemperatureError::timeout; - break; + lastResult = rslt; + badTemperatureCount = 0; } - - // Wait for the reading to complete (1 start bit + 40 data bits) - if (numPulses != 41) + else if (badTemperatureCount < MAX_BAD_TEMPERATURE_COUNT) + { + badTemperatureCount++; + } + else { - break; + lastResult = rslt; + lastTemperature = BAD_ERROR_TEMPERATURE; + lastHumidity = BAD_ERROR_TEMPERATURE; } + } +} - // We're done reading - reset the state and convert the pulses into final values - state = Initialising; - lastReadTime = millis(); +// Code executed by the DHT sensor task. +// This is run at the same priority as the Heat task, so it must not sit in any spin loops. +/*static*/ void DhtSensorHardwareInterface::SensorTask() +{ + for (;;) + { + for (DhtSensorHardwareInterface *&sensor : activeSensors) + { + { + MutexLocker lock(dhtMutex); - ProcessReadings(); - break; + if (sensor != nullptr) + { + sensor->TakeReading(); + } + } + delay(MinimumReadInterval/MaxSpiTempSensors); + } } } -#endif - -/*static*/ void DhtSensor::ProcessReadings() +// Process a reading. If success then update the temperature and humidity and return TemperatureError::success. +// Else return the TemperatureError code but do not update the readings. +TemperatureError DhtSensorHardwareInterface::ProcessReadings() { - // Check start bit - if (pulses[0] < 40) + // Check enough bits received and check start bit + if (numPulses != ARRAY_SIZE(pulses) || pulses[0] < MinimumOneBitStepClocks) { - lastResult = TemperatureError::ioError; - return; +// debugPrintf("pulses %u p0 %u\n", numPulses, (unsigned int)pulses[0]); + return TemperatureError::ioError; } // Reset 40 bits of received data to zero uint8_t data[5] = { 0, 0, 0, 0, 0 }; - // Inspect each high pulse and determine which ones - // are 0 (less than 40us) or 1 (more than 40us) + // Inspect each high pulse and determine which ones are 0 (less than 50us) or 1 (more than 50us). Ignore the start bit. for (size_t i = 0; i < 40; ++i) { data[i / 8] <<= 1; - if (pulses[i + 1] > 40) + if (pulses[i + 1] >= MinimumOneBitStepClocks) { data[i / 8] |= 1; } } +// debugPrintf("Data: %02x %02x %02x %02x %02x\n", data[0], data[1], data[2], data[3], data[4]); // Verify checksum if (((data[0] + data[1] + data[2] + data[3]) & 0xFF) != data[4]) { - lastResult = TemperatureError::ioError; - return; +// debugPrintf("Cks err\n"); + return TemperatureError::ioError; } // Generate final results @@ -362,8 +304,7 @@ void DhtDataTransition(CallbackParameter) case DhtSensorType::Dht11: lastHumidity = data[0]; lastTemperature = data[2]; - lastResult = TemperatureError::success; - break; + return TemperatureError::success; case DhtSensorType::Dht21: case DhtSensorType::Dht22: @@ -373,17 +314,65 @@ void DhtDataTransition(CallbackParameter) { lastTemperature *= -1.0; } - lastResult = TemperatureError::success; - break; + return TemperatureError::success; default: - lastHumidity = BAD_ERROR_TEMPERATURE; - lastTemperature = BAD_ERROR_TEMPERATURE; - lastResult = TemperatureError::notInitialised; - break; + return TemperatureError::notInitialised; } } +// Class DhtTemperatureSensor members +DhtTemperatureSensor::DhtTemperatureSensor(unsigned int channel) + : TemperatureSensor(channel, "DHT-temperature") +{ +} + +void DhtTemperatureSensor::Init() +{ + DhtSensorHardwareInterface::Create(GetSensorChannel() - FirstDhtTemperatureChannel); +} + +GCodeResult DhtTemperatureSensor::Configure(unsigned int mCode, unsigned int heater, GCodeBuffer& gb, const StringRef& reply) +{ + return DhtSensorHardwareInterface::Configure(this, GetSensorChannel() - FirstDhtTemperatureChannel, mCode, heater, gb, reply); +} + +DhtTemperatureSensor::~DhtTemperatureSensor() +{ + // We don't delete the hardware interface object because the humidity channel may still be using it +} + +TemperatureError DhtTemperatureSensor::GetTemperature(float& t) +{ + return DhtSensorHardwareInterface::GetTemperatureOrHumidity(GetSensorChannel() - FirstDhtTemperatureChannel, t, false); +} + +// Class DhtHumiditySensor members +DhtHumiditySensor::DhtHumiditySensor(unsigned int channel) + : TemperatureSensor(channel, "DHT-humidity") +{ +} + +void DhtHumiditySensor::Init() +{ + DhtSensorHardwareInterface::Create(GetSensorChannel() - FirstDhtHumidityChannel); +} + +GCodeResult DhtHumiditySensor::Configure(unsigned int mCode, unsigned int heater, GCodeBuffer& gb, const StringRef& reply) +{ + return DhtSensorHardwareInterface::Configure(this, GetSensorChannel() - FirstDhtHumidityChannel, mCode, heater, gb, reply); +} + +DhtHumiditySensor::~DhtHumiditySensor() +{ + // We don't delete the hardware interface object because the temperature channel may still be using it +} + +TemperatureError DhtHumiditySensor::GetTemperature(float& t) +{ + return DhtSensorHardwareInterface::GetTemperatureOrHumidity(GetSensorChannel() - FirstDhtHumidityChannel, t, true); +} + #endif // End diff --git a/src/Heating/Sensors/DhtSensor.h b/src/Heating/Sensors/DhtSensor.h index 4688e267..c81ac1e8 100644 --- a/src/Heating/Sensors/DhtSensor.h +++ b/src/Heating/Sensors/DhtSensor.h @@ -12,56 +12,80 @@ #if SUPPORT_DHT_SENSOR +#ifndef RTOS +# error DHT sensors are only supported in RTOS builds +#endif + # include "TemperatureSensor.h" # include "RTOSIface.h" enum class DhtSensorType { + none, Dht11, Dht21, Dht22 }; -class DhtSensor : public TemperatureSensor +// This class represents a DHT sensor attached to a particular SPI CS pin +class DhtSensorHardwareInterface { public: - friend class Heat; - - DhtSensor(unsigned int channel); - ~DhtSensor(); -#ifdef RTOS - static void SensorTask(); -#endif + static GCodeResult Configure(TemperatureSensor *ts, unsigned int relativeChannel, unsigned int mCode, unsigned int heater, GCodeBuffer& gb, const StringRef& reply); + void Interrupt(); - GCodeResult Configure(unsigned int mCode, unsigned int heater, GCodeBuffer& gb, const StringRef& reply) override; - void Init() override; + static DhtSensorHardwareInterface *Create(unsigned int relativeChannel); + static TemperatureError GetTemperatureOrHumidity(unsigned int relativeChannel, float& t, bool wantHumidity); static void InitStatic(); - TemperatureError GetTemperature(float& t) override; + static void SensorTask(); private: - static size_t numInstances; - static DhtSensorType type; - static TemperatureError lastResult; - static float lastTemperature, lastHumidity; - static size_t badTemperatureCount; + DhtSensorHardwareInterface(Pin p_pin); + + GCodeResult Configure(TemperatureSensor *ts, unsigned int mCode, unsigned int heater, GCodeBuffer& gb, const StringRef& reply); + TemperatureError GetTemperatureOrHumidity(float& t, bool wantHumidity) const; + void TakeReading(); + TemperatureError ProcessReadings(); + + static constexpr uint32_t DhtTaskStackWords = 100; // task stack size in dwords. 80 was not enough. Use 300 if debugging is enabled. static Mutex dhtMutex; + static Task<DhtTaskStackWords> *dhtTask; + static DhtSensorHardwareInterface *activeSensors[MaxSpiTempSensors]; -#ifndef RTOS - static uint32_t lastReadTime; - static enum SensorState - { - Initialising, - Starting, - Starting2, - Reading - } state; - static uint32_t lastOperationTime; - - static void Spin(); -#endif + Pin sensorPin; + DhtSensorType type; + TemperatureError lastResult; + float lastTemperature, lastHumidity; + size_t badTemperatureCount; + + volatile uint16_t lastPulseTime; + volatile size_t numPulses; + uint16_t pulses[41]; // 1 start bit + 40 data bits +}; + +// This class represents a DHT temperature sensor +class DhtTemperatureSensor : public TemperatureSensor +{ +public: + DhtTemperatureSensor(unsigned int channel); + ~DhtTemperatureSensor(); - static void ProcessReadings(); + TemperatureError GetTemperature(float& t) override; + GCodeResult Configure(unsigned int mCode, unsigned int heater, GCodeBuffer& gb, const StringRef& reply) override; + void Init() override; +}; + +// This class represents a DHT humidity sensor +class DhtHumiditySensor : public TemperatureSensor +{ +public: + DhtHumiditySensor(unsigned int channel); + ~DhtHumiditySensor(); + + TemperatureError GetTemperature(float& t) override; + GCodeResult Configure(unsigned int mCode, unsigned int heater, GCodeBuffer& gb, const StringRef& reply) override; + void Init() override; }; #endif diff --git a/src/Heating/Sensors/TemperatureSensor.cpp b/src/Heating/Sensors/TemperatureSensor.cpp index b5e1600a..2f97a41a 100644 --- a/src/Heating/Sensors/TemperatureSensor.cpp +++ b/src/Heating/Sensors/TemperatureSensor.cpp @@ -111,9 +111,13 @@ TemperatureSensor *TemperatureSensor::Create(unsigned int channel) ts = new CurrentLoopTemperatureSensor(channel); } #if SUPPORT_DHT_SENSOR - else if (channel == DhtTemperatureChannel || channel == DhtHumidityChannel) + else if (FirstDhtTemperatureChannel <= channel && channel < FirstDhtTemperatureChannel + MaxSpiTempSensors) { - ts = new DhtSensor(channel); + ts = new DhtTemperatureSensor(channel); + } + else if (FirstDhtHumidityChannel <= channel && channel < FirstDhtHumidityChannel + MaxSpiTempSensors) + { + ts = new DhtHumiditySensor(channel); } #endif #if HAS_CPU_TEMP_SENSOR @@ -123,7 +127,7 @@ TemperatureSensor *TemperatureSensor::Create(unsigned int channel) } #endif #if HAS_SMART_DRIVERS - else if (channel >= FirstTmcDriversSenseChannel && channel < FirstTmcDriversSenseChannel + 2) + else if (channel >= FirstTmcDriversSenseChannel && channel < FirstTmcDriversSenseChannel + NumTmcDriversSenseChannels) { ts = new TmcDriverTemperatureSensor(channel); } diff --git a/src/Heating/Sensors/TemperatureSensor.h b/src/Heating/Sensors/TemperatureSensor.h index fdb04775..fe5f6b59 100644 --- a/src/Heating/Sensors/TemperatureSensor.h +++ b/src/Heating/Sensors/TemperatureSensor.h @@ -41,12 +41,13 @@ public: // Get the name. Returns nullptr if no name has been assigned. const char *GetHeaterName() const { return heaterName; } + // Copy the basic details to the reply buffer + void CopyBasicHeaterDetails(unsigned int heater, const StringRef& reply) const; + // Factory method static TemperatureSensor *Create(unsigned int channel); protected: - void CopyBasicHeaterDetails(unsigned int heater, const StringRef& reply) const; - static TemperatureError GetPT100Temperature(float& t, uint16_t ohmsx100); // shared function used by two derived classes private: diff --git a/src/Movement/DDA.cpp b/src/Movement/DDA.cpp index d8fe556f..a969c6dc 100644 --- a/src/Movement/DDA.cpp +++ b/src/Movement/DDA.cpp @@ -381,7 +381,6 @@ bool DDA::Init(GCodes::RawMove &nextMove, bool doMotorMapping) xAxes = nextMove.xAxes; yAxes = nextMove.yAxes; endStopsToCheck = nextMove.endStopsToCheck; - canPauseBefore = nextMove.canPauseBefore; canPauseAfter = nextMove.canPauseAfter; usingStandardFeedrate = nextMove.usingStandardFeedrate; filePos = nextMove.filePos; @@ -537,7 +536,6 @@ bool DDA::Init(const float_t adjustments[DRIVES]) isPrintingMove = false; xyMoving = false; endStopsToCheck = 0; - canPauseBefore = true; canPauseAfter = true; usingStandardFeedrate = false; usePressureAdvance = false; @@ -897,7 +895,7 @@ void DDA::RecalculateMove() // We need to set the number of clocks needed here because we use it before the move has been frozen const float totalTime = (2 * topSpeed - startSpeed - endSpeed)/acceleration + (totalDistance - accelDistance - decelDistance)/topSpeed; - clocksNeeded = (uint32_t)(totalTime * stepClockRate); + clocksNeeded = (uint32_t)(totalTime * StepClockRate); } // Decide what speed we would really like this move to end at. @@ -1027,10 +1025,10 @@ void DDA::Prepare(uint8_t simMode) const float accelStopTime = (topSpeed - startSpeed)/acceleration; const float decelStartTime = accelStopTime + (params.decelStartDistance - accelDistance)/topSpeed; - startSpeedTimesCdivA = (uint32_t)roundU32((startSpeed * stepClockRate)/acceleration); - params.topSpeedTimesCdivA = (uint32_t)roundU32((topSpeed * stepClockRate)/acceleration); - topSpeedTimesCdivAPlusDecelStartClocks = params.topSpeedTimesCdivA + (uint32_t)roundU32(decelStartTime * stepClockRate); - extraAccelerationClocks = roundS32((accelStopTime - (accelDistance/topSpeed)) * stepClockRate); + startSpeedTimesCdivA = (uint32_t)roundU32((startSpeed * StepClockRate)/acceleration); + params.topSpeedTimesCdivA = (uint32_t)roundU32((topSpeed * StepClockRate)/acceleration); + topSpeedTimesCdivAPlusDecelStartClocks = params.topSpeedTimesCdivA + (uint32_t)roundU32(decelStartTime * StepClockRate); + extraAccelerationClocks = roundS32((accelStopTime - (accelDistance/topSpeed)) * StepClockRate); params.compFactor = (topSpeed - startSpeed)/topSpeed; firstDM = nullptr; @@ -1542,9 +1540,21 @@ bool DDA::Step() break; } - // 7. Schedule next interrupt, or if it would be too soon, generate more steps immediately + // 7. Check whether we have been in this ISR for too long already and need to take a break + uint32_t nextStepDue = firstDM->nextStepTime + moveStartTime; + const uint32_t clocksTaken = (Platform::GetInterruptClocks16() - isrStartTime) & 0x0000FFFF; + if (clocksTaken >= DDA::MaxStepInterruptTime && (nextStepDue - isrStartTime) < (clocksTaken + DDA::MinInterruptInterval)) + { + // Force a break by updating the move start time + const uint32_t delayClocks = (clocksTaken + DDA::MinInterruptInterval) - (nextStepDue - isrStartTime); + moveStartTime += delayClocks; + nextStepDue += delayClocks; + ++numHiccups; + } + + // 8. Schedule next interrupt, or if it would be too soon, generate more steps immediately // If we have already spent too much time in the ISR, delay the interrupt - repeat = platform.ScheduleStepInterruptWithLimit(firstDM->nextStepTime + moveStartTime, isrStartTime); + repeat = platform.ScheduleStepInterrupt(nextStepDue); } while (repeat); if (state == completed) diff --git a/src/Movement/DDA.h b/src/Movement/DDA.h index 45f085c4..066f3405 100644 --- a/src/Movement/DDA.h +++ b/src/Movement/DDA.h @@ -50,7 +50,6 @@ public: void Prepare(uint8_t simMode) __attribute__ ((hot)); // Calculate all the values and freeze this DDA bool HasStepError() const; bool CanPauseAfter() const { return canPauseAfter; } - bool CanPauseBefore() const { return canPauseBefore; } bool IsPrintingMove() const { return isPrintingMove; } // Return true if this involves both XY movement and extrusion bool UsingStandardFeedrate() const { return usingStandardFeedrate; } @@ -96,9 +95,6 @@ public: void DebugPrint() const; // print the DDA only void DebugPrintAll() const; // print the DDA and active DMs - static constexpr uint32_t stepClockRate = VARIANT_MCK/128; // the frequency of the clock used for stepper pulse timing (see Platform::InitialiseInterrupts) - static constexpr uint64_t stepClockRateSquared = (uint64_t)stepClockRate * stepClockRate; - // Note on the following constant: // If we calculate the step interval on every clock, we reach a point where the calculation time exceeds the step interval. // The worst case is pure Z movement on a delta. On a Mini Kossel with 80 steps/mm with this firmware running on a Duet (84MHx SAM3X8 processor), @@ -107,16 +103,16 @@ public: // Note: the above measurements were taken some time ago, before some firmware optimisations. #if SAME70 // The system clock of the SAME70 is running at 150MHz. Use the same defaults as for the SAM4E for now. - static constexpr uint32_t MinCalcIntervalDelta = (40 * stepClockRate)/1000000; // the smallest sensible interval between calculations (40us) in step timer clocks - static constexpr uint32_t MinCalcIntervalCartesian = (40 * stepClockRate)/1000000; // same as delta for now, but could be lower + static constexpr uint32_t MinCalcIntervalDelta = (40 * StepClockRate)/1000000; // the smallest sensible interval between calculations (40us) in step timer clocks + static constexpr uint32_t MinCalcIntervalCartesian = (40 * StepClockRate)/1000000; // same as delta for now, but could be lower static constexpr uint32_t MinInterruptInterval = 6; // about 6us minimum interval between interrupts, in step clocks #elif SAM4E || SAM4S - static constexpr uint32_t MinCalcIntervalDelta = (40 * stepClockRate)/1000000; // the smallest sensible interval between calculations (40us) in step timer clocks - static constexpr uint32_t MinCalcIntervalCartesian = (40 * stepClockRate)/1000000; // same as delta for now, but could be lower + static constexpr uint32_t MinCalcIntervalDelta = (40 * StepClockRate)/1000000; // the smallest sensible interval between calculations (40us) in step timer clocks + static constexpr uint32_t MinCalcIntervalCartesian = (40 * StepClockRate)/1000000; // same as delta for now, but could be lower static constexpr uint32_t MinInterruptInterval = 6; // about 6us minimum interval between interrupts, in step clocks #else - static constexpr uint32_t MinCalcIntervalDelta = (60 * stepClockRate)/1000000; // the smallest sensible interval between calculations (60us) in step timer clocks - static constexpr uint32_t MinCalcIntervalCartesian = (60 * stepClockRate)/1000000; // same as delta for now, but could be lower + static constexpr uint32_t MinCalcIntervalDelta = (60 * StepClockRate)/1000000; // the smallest sensible interval between calculations (60us) in step timer clocks + static constexpr uint32_t MinCalcIntervalCartesian = (60 * StepClockRate)/1000000; // same as delta for now, but could be lower static constexpr uint32_t MinInterruptInterval = 4; // about 6us minimum interval between interrupts, in step clocks #endif static constexpr uint32_t MaxStepInterruptTime = 10 * MinInterruptInterval; // the maximum time we spend looping in the ISR , in step clocks @@ -167,7 +163,6 @@ private: uint8_t endCoordinatesValid : 1; // True if endCoordinates can be relied on uint8_t isDeltaMovement : 1; // True if this is a delta printer movement uint8_t canPauseAfter : 1; // True if we can pause at the end of this move - uint8_t canPauseBefore : 1; // True if we can pause just before this move uint8_t isPrintingMove : 1; // True if this move includes XY movement and extrusion uint8_t usePressureAdvance : 1; // True if pressure advance should be applied to any forward extrusion uint8_t hadLookaheadUnderrun : 1; // True if the lookahead queue was not long enough to optimise this move diff --git a/src/Movement/DriveMovement.cpp b/src/Movement/DriveMovement.cpp index 5afcf344..f510d0a2 100644 --- a/src/Movement/DriveMovement.cpp +++ b/src/Movement/DriveMovement.cpp @@ -58,14 +58,14 @@ DriveMovement::DriveMovement(DriveMovement *next) : nextDM(next) void DriveMovement::PrepareCartesianAxis(const DDA& dda, const PrepParams& params) { const float stepsPerMm = (float)totalSteps/dda.totalDistance; - mp.cart.twoCsquaredTimesMmPerStepDivA = roundU64((double)(DDA::stepClockRateSquared * 2)/((double)stepsPerMm * (double)dda.acceleration)); + mp.cart.twoCsquaredTimesMmPerStepDivA = roundU64((double)(StepClockRateSquared * 2)/((double)stepsPerMm * (double)dda.acceleration)); // Acceleration phase parameters mp.cart.accelStopStep = (uint32_t)(dda.accelDistance * stepsPerMm) + 1; mp.cart.compensationClocks = mp.cart.accelCompensationClocks = 0; // Constant speed phase parameters - mp.cart.mmPerStepTimesCKdivtopSpeed = roundU32(((float)((uint64_t)DDA::stepClockRate * K1))/(stepsPerMm * dda.topSpeed)); + mp.cart.mmPerStepTimesCKdivtopSpeed = roundU32(((float)((uint64_t)StepClockRate * K1))/(stepsPerMm * dda.topSpeed)); // Deceleration phase parameters // First check whether there is any deceleration at all, otherwise we may get strange results because of rounding errors @@ -78,7 +78,7 @@ void DriveMovement::PrepareCartesianAxis(const DDA& dda, const PrepParams& param { mp.cart.decelStartStep = (uint32_t)(params.decelStartDistance * stepsPerMm) + 1; const uint64_t initialDecelSpeedTimesCdivASquared = isquare64(params.topSpeedTimesCdivA); - twoDistanceToStopTimesCsquaredDivA = initialDecelSpeedTimesCdivASquared + roundU64((params.decelStartDistance * (DDA::stepClockRateSquared * 2))/dda.acceleration); + twoDistanceToStopTimesCsquaredDivA = initialDecelSpeedTimesCdivASquared + roundU64((params.decelStartDistance * (StepClockRateSquared * 2))/dda.acceleration); } // No reverse phase @@ -98,7 +98,7 @@ void DriveMovement::PrepareDeltaAxis(const DDA& dda, const PrepParams& params) mp.delta.hmz0sK = roundS32(h0MinusZ0 * stepsPerMm * DriveMovement::K2); mp.delta.minusAaPlusBbTimesKs = -roundS32(aAplusbB * stepsPerMm * DriveMovement::K2); mp.delta.dSquaredMinusAsquaredMinusBsquaredTimesKsquaredSsquared = roundS64(dSquaredMinusAsquaredMinusBsquared * fsquare(stepsPerMm * DriveMovement::K2)); - mp.delta.twoCsquaredTimesMmPerStepDivA = roundU64((double)(2 * DDA::stepClockRateSquared)/((double)stepsPerMm * (double)dda.acceleration)); + mp.delta.twoCsquaredTimesMmPerStepDivA = roundU64((double)(2 * StepClockRateSquared)/((double)stepsPerMm * (double)dda.acceleration)); // Calculate the distance at which we need to reverse direction. if (params.a2plusb2 <= 0.0) @@ -152,7 +152,7 @@ void DriveMovement::PrepareDeltaAxis(const DDA& dda, const PrepParams& params) mp.delta.accelStopDsK = roundU32(dda.accelDistance * stepsPerMm * K2); // Constant speed phase parameters - mp.delta.mmPerStepTimesCKdivtopSpeed = roundU32(((float)DDA::stepClockRate * K1)/(stepsPerMm * dda.topSpeed)); + mp.delta.mmPerStepTimesCKdivtopSpeed = roundU32(((float)StepClockRate * K1)/(stepsPerMm * dda.topSpeed)); // Deceleration phase parameters // First check whether there is any deceleration at all, otherwise we may get strange results because of rounding errors @@ -164,7 +164,7 @@ void DriveMovement::PrepareDeltaAxis(const DDA& dda, const PrepParams& params) else { mp.delta.decelStartDsK = roundU32(params.decelStartDistance * stepsPerMm * K2); - twoDistanceToStopTimesCsquaredDivA = isquare64(params.topSpeedTimesCdivA) + roundU64((params.decelStartDistance * (DDA::stepClockRateSquared * 2))/dda.acceleration); + twoDistanceToStopTimesCsquaredDivA = isquare64(params.topSpeedTimesCdivA) + roundU64((params.decelStartDistance * (StepClockRateSquared * 2))/dda.acceleration); } } @@ -181,7 +181,7 @@ void DriveMovement::PrepareExtruder(const DDA& dda, const PrepParams& params, fl float a, b, limit; if (reprap.GetPlatform().GetExtrusionCoefficients(extruder, a, b, limit)) { - const float averageExtrusionSpeed = (dda.totalDistance * dv * DDA::stepClockRate)/dda.clocksNeeded; + const float averageExtrusionSpeed = (dda.totalDistance * dv * StepClockRate)/dda.clocksNeeded; const float factor = 1.0 + min<float>((averageExtrusionSpeed * a) + (averageExtrusionSpeed * averageExtrusionSpeed * b), limit); stepsPerMm *= factor; } @@ -196,8 +196,8 @@ void DriveMovement::PrepareExtruder(const DDA& dda, const PrepParams& params, fl { // Calculate the pressure advance parameters compensationTime = reprap.GetPlatform().GetPressureAdvance(extruder); - mp.cart.compensationClocks = roundU32(compensationTime * (float)DDA::stepClockRate); - mp.cart.accelCompensationClocks = roundU32(compensationTime * (float)DDA::stepClockRate * params.compFactor); + mp.cart.compensationClocks = roundU32(compensationTime * (float)StepClockRate); + mp.cart.accelCompensationClocks = roundU32(compensationTime * (float)StepClockRate * params.compFactor); #ifdef COMPENSATE_SPEED_CHANGES // If there is a speed change at the start of the move, theoretically we should instantly advance or retard the filament by the associated compensation amount. @@ -223,10 +223,10 @@ void DriveMovement::PrepareExtruder(const DDA& dda, const PrepParams& params, fl mp.cart.accelStopStep = (uint32_t)(dda.accelDistance * stepsPerMm) + 1; } - mp.cart.twoCsquaredTimesMmPerStepDivA = roundU64((double)(DDA::stepClockRateSquared * 2)/((double)stepsPerMm * (double)dda.acceleration)); + mp.cart.twoCsquaredTimesMmPerStepDivA = roundU64((double)(StepClockRateSquared * 2)/((double)stepsPerMm * (double)dda.acceleration)); // Constant speed phase parameters - mp.cart.mmPerStepTimesCKdivtopSpeed = (uint32_t)((float)((uint64_t)DDA::stepClockRate * K1)/(stepsPerMm * dda.topSpeed)); + mp.cart.mmPerStepTimesCKdivtopSpeed = (uint32_t)((float)((uint64_t)StepClockRate * K1)/(stepsPerMm * dda.topSpeed)); // Calculate the deceleration and reverse phase parameters and update totalSteps // First check whether there is any deceleration at all, otherwise we may get strange results because of rounding errors @@ -243,7 +243,7 @@ void DriveMovement::PrepareExtruder(const DDA& dda, const PrepParams& params, fl const int32_t initialDecelSpeedTimesCdivA = (int32_t)params.topSpeedTimesCdivA - (int32_t)mp.cart.compensationClocks; // signed because it may be negative and we square it const uint64_t initialDecelSpeedTimesCdivASquared = isquare64(initialDecelSpeedTimesCdivA); twoDistanceToStopTimesCsquaredDivA = - initialDecelSpeedTimesCdivASquared + roundU64(((params.decelStartDistance + accelCompensationDistance) * (float)(DDA::stepClockRateSquared * 2))/dda.acceleration); + initialDecelSpeedTimesCdivASquared + roundU64(((params.decelStartDistance + accelCompensationDistance) * (float)(StepClockRateSquared * 2))/dda.acceleration); // See whether there is a reverse phase const float compensationSpeedChange = dda.acceleration * compensationTime; diff --git a/src/Movement/Move.cpp b/src/Movement/Move.cpp index 9dcf6cb6..1765ac71 100644 --- a/src/Movement/Move.cpp +++ b/src/Movement/Move.cpp @@ -37,8 +37,8 @@ #include "Platform.h" #include "Tools/Tool.h" -static constexpr uint32_t UsualMinimumPreparedTime = DDA::stepClockRate/10; // 100ms -static constexpr uint32_t AbsoluteMinimumPreparedTime = DDA::stepClockRate/20; // 50ms +constexpr uint32_t UsualMinimumPreparedTime = StepClockRate/10; // 100ms +constexpr uint32_t AbsoluteMinimumPreparedTime = StepClockRate/20; // 50ms Move::Move() : currentDda(nullptr), active(false), scheduledMoves(0), completedMoves(0) { @@ -197,7 +197,7 @@ void Move::Spin() prevMoveTime = dda->GetClocksNeeded(); } - canAddMove = (unPreparedTime < DDA::stepClockRate/2 || unPreparedTime + prevMoveTime < 2 * DDA::stepClockRate); + canAddMove = (unPreparedTime < StepClockRate/2 || unPreparedTime + prevMoveTime < 2 * StepClockRate); } if (canAddMove) @@ -283,7 +283,7 @@ void Move::Spin() DDA *cdda; // currentDda is declared volatile, so copy it in the next line if (simulationMode != 0 && (cdda = currentDda) != nullptr) { - simulationTime += (float)cdda->GetClocksNeeded()/DDA::stepClockRate; + simulationTime += (float)cdda->GetClocksNeeded()/StepClockRate; cdda->Complete(); CurrentMoveCompleted(); } @@ -455,7 +455,7 @@ bool Move::PausePrint(RestorePoint& rp) while (dda != savedDdaRingAddPointer) { - if (pauseOkHere && dda->CanPauseBefore()) + if (pauseOkHere) { // We can pause before executing this move ddaRingAddPointer = dda; @@ -477,8 +477,6 @@ bool Move::PausePrint(RestorePoint& rp) InverseAxisAndBedTransform(rp.moveCoords, prevDda->GetXAxes(), prevDda->GetYAxes()); // we assume that xAxes hasn't changed between the moves - rp.proportionDone = ddaRingAddPointer->GetProportionDone(false); // get the proportion of the current multi-segment move that has been completed - #if SUPPORT_IOBITS rp.ioBits = dda->GetIoBits(); #endif @@ -489,6 +487,7 @@ bool Move::PausePrint(RestorePoint& rp) } dda = ddaRingAddPointer; + rp.proportionDone = dda->GetProportionDone(false); // get the proportion of the current multi-segment move that has been completed if (dda->UsingStandardFeedrate()) { rp.feedRate = dda->GetRequestedSpeed(); diff --git a/src/Networking/Network.cpp b/src/Networking/Network.cpp index bdb49f9a..ddfc9099 100644 --- a/src/Networking/Network.cpp +++ b/src/Networking/Network.cpp @@ -91,6 +91,9 @@ void Network::Init() { iface->Init(); } + + fastLoop = UINT32_MAX; + slowLoop = 0; } GCodeResult Network::EnableProtocol(unsigned int interface, NetworkProtocol protocol, int port, int secure, const StringRef& reply) @@ -265,6 +268,8 @@ bool Network::IsWiFiInterface(unsigned int interface) const // Main spin loop. If 'full' is true then we are being called from the main spin loop. If false then we are being called during HSMCI idle time. void Network::Spin(bool full) { + const uint32_t lastTime = Platform::GetInterruptClocks(); + // Keep the network modules running for (NetworkInterface *iface : interfaces) { @@ -289,6 +294,17 @@ void Network::Spin(bool full) } HttpResponder::CheckSessions(); // time out any sessions that have gone away + + // Keep track of the loop time + const uint32_t dt = Platform::GetInterruptClocks() - lastTime; + if (dt < fastLoop) + { + fastLoop = dt; + } + if (dt > slowLoop) + { + slowLoop = dt; + } } // Process the network timer interrupt @@ -303,6 +319,11 @@ void Network::Interrupt() void Network::Diagnostics(MessageType mtype) { platform.Message(mtype, "=== Network ===\n"); + + platform.MessageF(mtype, "Slowest loop: %.2fms; fastest: %.2fms\n", (double)(slowLoop * StepClocksToMillis), (double)(fastLoop * StepClocksToMillis)); + fastLoop = UINT32_MAX; + slowLoop = 0; + platform.Message(mtype, "Responder states:"); for (NetworkResponder *r = responders; r != nullptr; r = r->GetNext()) { diff --git a/src/Networking/Network.h b/src/Networking/Network.h index c7e84e82..0355e625 100644 --- a/src/Networking/Network.h +++ b/src/Networking/Network.h @@ -88,6 +88,8 @@ private: Mutex httpMutex, telnetMutex; + uint32_t fastLoop, slowLoop; + char hostname[16]; // Limit DHCP hostname to 15 characters + terminating 0 }; diff --git a/src/Platform.cpp b/src/Platform.cpp index 5ca13ac7..45c669f3 100644 --- a/src/Platform.cpp +++ b/src/Platform.cpp @@ -1833,7 +1833,7 @@ static void FanInterrupt(CallbackParameter) ++fanInterruptCount; if (fanInterruptCount == fanMaxInterruptCount) { - const uint32_t now = micros(); + const uint32_t now = Platform::GetInterruptClocks(); fanInterval = now - fanLastResetTime; fanLastResetTime = now; fanInterruptCount = 0; @@ -2427,8 +2427,8 @@ bool Platform::DiagnosticTest(GCodeBuffer& gb, const StringRef& reply, int d) } } reply.printf("Square roots: 62-bit %.2fus %s, 32-bit %.2fus %s\n", - (double)(tim1 * 10000)/DDA::stepClockRate, (ok1) ? "ok" : "ERROR", - (double)(tim2 * 10000)/DDA::stepClockRate, (ok2) ? "ok" : "ERROR"); + (double)(tim1 * 10000)/StepClockRate, (ok1) ? "ok" : "ERROR", + (double)(tim2 * 10000)/StepClockRate, (ok2) ? "ok" : "ERROR"); } break; @@ -3126,7 +3126,7 @@ void Platform::SetDriverStepTiming(size_t driver, const float microseconds[4]) if (microseconds[i] > MinStepPulseTiming) { slowDriversBitmap |= CalcDriverBitmap(driver); // this drive does need extended timing - const uint32_t clocks = (uint32_t)(((float)DDA::stepClockRate * microseconds[i] * 0.000001) + 0.99); // convert microseconds to step clocks, rounding up + const uint32_t clocks = (uint32_t)(((float)StepClockRate * microseconds[i] * 0.000001) + 0.99); // convert microseconds to step clocks, rounding up if (clocks > slowDriverStepTimingClocks[i]) { slowDriverStepTimingClocks[i] = clocks; @@ -3141,7 +3141,7 @@ void Platform::GetDriverStepTiming(size_t driver, float microseconds[4]) const for (size_t i = 0; i < 4; ++i) { microseconds[i] = (isSlowDriver) - ? (float)slowDriverStepTimingClocks[i] * 1000000.0/(float)DDA::stepClockRate + ? (float)slowDriverStepTimingClocks[i] * 1000000.0/(float)StepClockRate : 0.0; } } @@ -3207,9 +3207,9 @@ float Platform::GetFanRPM() const // We get 2 tacho pulses per revolution, hence 2 interrupts per revolution. // However, if the fan stops then we get no interrupts and fanInterval stops getting updated. // We must recognise this and return zero. - return (fanInterval != 0 && micros() - fanLastResetTime < 3000000U) // if we have a reading and it is less than 3 second old - ? (float)((30000000U * fanMaxInterruptCount)/fanInterval) // then calculate RPM assuming 2 interrupts per rev - : 0.0; // else assume fan is off or tacho not connected + return (fanInterval != 0 && Platform::GetInterruptClocks() - fanLastResetTime < 3 * StepClockRate) // if we have a reading and it is less than 3 second old + ? (float)(3 * StepClockRate * fanMaxInterruptCount)/fanInterval // then calculate RPM assuming 2 interrupts per rev + : 0.0; // else assume fan is off or tacho not connected } bool Platform::FansHardwareInverted(size_t fanNumber) const @@ -4447,39 +4447,6 @@ void STEP_TC_HANDLER() return false; } -// Schedule an interrupt at the specified clock count, or return true if it has passed already -// This version limits the time we can spend in the ISR -/*static*/ bool Platform::ScheduleStepInterruptWithLimit(uint32_t tim, uint32_t isrStartTime) -{ - const irqflags_t flags = cpu_irq_save(); - const uint32_t iClocks = GetInterruptClocksInterruptsDisabled(); - if ((int32_t)(tim - iClocks) < (int32_t)DDA::MinInterruptInterval) // if less than about 6us to go or already passed - { - if (iClocks - isrStartTime < DDA::MaxStepInterruptTime) // if we haven't already spent too much time looping inside the ISR - { - cpu_irq_restore(flags); - return true; // tell the caller to simulate an interrupt instead - } - tim = iClocks + DDA::MinInterruptInterval; // delay the interrupt to avoid using all the CPU time - ++DDA::numHiccups; - } - - STEP_TC->TC_CHANNEL[STEP_TC_CHAN].TC_RA = tim; // set up the compare register - - // We would like to clear any pending step interrupt. To do this, we must read the TC status register. - // Unfortunately, this would clear any other pending interrupts from the same TC. - // So we don't, and the step ISR must allow for getting called prematurely. - STEP_TC->TC_CHANNEL[STEP_TC_CHAN].TC_IER = TC_IER_CPAS; // enable the interrupt - cpu_irq_restore(flags); - -#ifdef MOVE_DEBUG - ++numInterruptsScheduled; - nextInterruptTime = tim; - nextInterruptScheduledAt = Platform::GetInterruptClocks(); -#endif - return false; -} - // Make sure we get no step interrupts /*static*/ void Platform::DisableStepInterrupt() { diff --git a/src/Platform.h b/src/Platform.h index 4d51e2e2..201c5cd4 100644 --- a/src/Platform.h +++ b/src/Platform.h @@ -279,10 +279,11 @@ typedef AveragingFilter<Z_PROBE_AVERAGE_READINGS> ZProbeAveragingFilter; // Enumeration of error condition bits enum class ErrorCode : uint32_t { - BadTemp = 1 << 0, - BadMove = 1 << 1, - OutputStarvation = 1 << 2, - OutputStackOverflow = 1 << 3 + BadTemp = 1u << 0, + BadMove = 1u << 1, + OutputStarvation = 1u << 2, + OutputStackOverflow = 1u << 3, + HsmciTimeout = 1u << 4 }; struct AxisDriversConfig @@ -332,8 +333,8 @@ public: // Timing static uint32_t GetInterruptClocks() __attribute__ ((hot)); // Get the interrupt clock count static uint32_t GetInterruptClocksInterruptsDisabled() __attribute__ ((hot)); // Get the interrupt clock count, when we know already that interrupts are disabled + static uint16_t GetInterruptClocks16(); // Get the interrupt clock count when we only care about the lowest 16 bits static bool ScheduleStepInterrupt(uint32_t tim) __attribute__ ((hot)); // Schedule an interrupt at the specified clock count, or return true if it has passed already - static bool ScheduleStepInterruptWithLimit(uint32_t tim, uint32_t isrStartTime) __attribute__ ((hot)); // Schedule an interrupt at the specified clock count, or return true if it has passed already static void DisableStepInterrupt(); // Make sure we get no step interrupts static bool ScheduleSoftTimerInterrupt(uint32_t tim); // Schedule an interrupt at the specified clock count, or return true if it has passed already static void DisableSoftTimerInterrupt(); // Make sure we get no software timer interrupts @@ -564,6 +565,7 @@ public: #if HAS_SMART_DRIVERS float GetTmcDriversTemperature(unsigned int board) const; void DriverCoolingFansOn(uint32_t driverChannelsMonitored); + unsigned int GetNumSmartDrivers() const { return numSmartDrivers; } #endif #if HAS_STALL_DETECT @@ -1161,6 +1163,12 @@ inline float Platform::GetPressureAdvance(size_t extruder) const #endif +// Get the interrupt clock count when we only care about the lowest 16 bits. More efficient than calling GetInterruptClocks on platforms with 16-bit timers. +/*static*/ inline uint16_t Platform::GetInterruptClocks16() +{ + return (uint16_t)STEP_TC->TC_CHANNEL[STEP_TC_CHAN].TC_CV; +} + // This is called by the tick ISR to get the raw Z probe reading to feed to the filter inline uint16_t Platform::GetRawZProbeReading() const { diff --git a/src/PortControl.cpp b/src/PortControl.cpp index 7af80de5..3e6d7f0a 100644 --- a/src/PortControl.cpp +++ b/src/PortControl.cpp @@ -101,7 +101,7 @@ bool PortControl::Configure(GCodeBuffer& gb, const StringRef& reply) { seen = true; advanceMillis = (unsigned int)constrain<int>(gb.GetIValue(), 0, 1000); - advanceClocks = (advanceMillis * (uint64_t)DDA::stepClockRate)/1000; + advanceClocks = (advanceMillis * (uint64_t)StepClockRate)/1000; } if (!seen) { diff --git a/src/RepRap.cpp b/src/RepRap.cpp index b55b84bb..0c426c9c 100644 --- a/src/RepRap.cpp +++ b/src/RepRap.cpp @@ -33,6 +33,9 @@ # include "FreeRTOS.h" # include "task.h" +// We call vTaskNotifyGiveFromISR from various interrupts, so the following must be true +static_assert(configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY <= NvicPriorityHSMCI, "configMAX_SYSCALL_INTERRUPT_PRIORITY is set too high"); + static TaskHandle_t hsmciTask = nullptr; // the task that is waiting for a HSMCI command to complete // Callback function from the hsmci driver, called while it is waiting for an SD card operation to complete @@ -52,7 +55,11 @@ extern "C" void hsmciIdle(uint32_t stBits, uint32_t dmaBits) #if SAME70 XDMAC->XDMAC_CHID[CONF_HSMCI_XDMAC_CHANNEL].XDMAC_CIE = dmaBits; #endif - ulTaskNotifyTake(pdTRUE, 200); + if (ulTaskNotifyTake(pdTRUE, 200) == 0) + { + // We timed out waiting for the HSMCI operation to complete + reprap.GetPlatform().LogError(ErrorCode::HsmciTimeout); + } } } @@ -152,7 +159,7 @@ void RepRap::Init() platform->Init(); network->Init(); - SetName(DEFAULT_MACHINE_NAME); // network must be initialised before calling this because this calls SetHostName + SetName(DEFAULT_MACHINE_NAME); // Network must be initialised before calling this because this calls SetHostName gCodes->Init(); move->Init(); heat->Init(); @@ -166,6 +173,7 @@ void RepRap::Init() portControl->Init(); #endif printMonitor->Init(); + FilamentMonitor::InitStatic(); #if SUPPORT_12864_LCD display->Init(); #endif @@ -223,7 +231,6 @@ void RepRap::Init() fastLoop = UINT32_MAX; slowLoop = 0; - lastTime = micros(); } void RepRap::Exit() @@ -250,8 +257,12 @@ void RepRap::Exit() void RepRap::Spin() { - if(!active) + if (!active) + { return; + } + + const uint32_t lastTime = Platform::GetInterruptClocks(); ticksInSpinState = 0; spinningModule = modulePlatform; @@ -344,8 +355,7 @@ void RepRap::Spin() } // Keep track of the loop time - const uint32_t t = micros(); - const uint32_t dt = t - lastTime; + const uint32_t dt = Platform::GetInterruptClocks() - lastTime; if (dt < fastLoop) { fastLoop = dt; @@ -354,14 +364,13 @@ void RepRap::Spin() { slowLoop = dt; } - lastTime = t; RTOSIface::Yield(); } void RepRap::Timing(MessageType mtype) { - platform->MessageF(mtype, "Slowest main loop (seconds): %f; fastest: %f\n", (double)(slowLoop * 0.000001), (double)(fastLoop * 0.000001)); + platform->MessageF(mtype, "Slowest loop: %.2fms; fastest: %.2fms\n", (double)(slowLoop * StepClocksToMillis), (double)(fastLoop * StepClocksToMillis)); fastLoop = UINT32_MAX; slowLoop = 0; } @@ -405,9 +414,26 @@ void RepRap::EmergencyStop() { stopped = true; - // Do not turn off ATX power here. If the nozzles are still hot, don't risk melting any surrounding parts... + // Do not turn off ATX power here. If the nozzles are still hot, don't risk melting any surrounding parts by turning fans off. //platform->SetAtxPower(false); + switch (gCodes->GetMachineType()) + { + case MachineType::cnc: + for (size_t i = 0; i < MaxSpindles; i++) + { + platform->AccessSpindle(i).TurnOff(); + } + break; + + case MachineType::laser: + platform->SetLaserPwm(0.0); + break; + + default: + break; + } + // Deselect all tools (is this necessary?) { MutexLocker lock(toolListMutex); diff --git a/src/RepRap.h b/src/RepRap.h index 09f76796..213adde3 100644 --- a/src/RepRap.h +++ b/src/RepRap.h @@ -153,7 +153,6 @@ private: uint16_t ticksInSpinState; Module spinningModule; uint32_t fastLoop, slowLoop; - uint32_t lastTime; uint32_t debug; bool stopped; diff --git a/src/RepRapFirmware.h b/src/RepRapFirmware.h index fd4eda8d..b23855a8 100644 --- a/src/RepRapFirmware.h +++ b/src/RepRapFirmware.h @@ -224,6 +224,9 @@ template<typename BitmapType> BitmapType UnsignedArrayToBitMap(const uint32_t *a } // Common definitions used by more than one module +constexpr uint32_t StepClockRate = VARIANT_MCK/128; // the frequency of the clock used for stepper pulse timing (see Platform::InitialiseInterrupts) +constexpr uint64_t StepClockRateSquared = (uint64_t)StepClockRate * StepClockRate; + constexpr size_t ScratchStringLength = 220; // standard length of a scratch string, enough to print delta parameters to constexpr size_t ShortScratchStringLength = 50; @@ -238,6 +241,7 @@ constexpr float MinutesToSeconds = 60.0; constexpr float SecondsToMinutes = 1.0/MinutesToSeconds; constexpr float SecondsToMillis = 1000.0; constexpr float MillisToSeconds = 0.001; +constexpr float StepClocksToMillis = 1000.0/(float)StepClockRate; constexpr float InchToMm = 25.4; constexpr float Pi = 3.141592653589793; constexpr float TwoPi = 3.141592653589793 * 2; @@ -256,20 +260,28 @@ const uint32_t NvicPriorityWatchdog = 0; // the secondary watchdog has the high #endif const uint32_t NvicPriorityPanelDueUart = 1; // UART is highest to avoid character loss (it has only a 1-character receive buffer) -const uint32_t NvicPriorityDriversSerialTMC = 2;// USART or UART used to control and monitor the smart drivers +const uint32_t NvicPriorityDriversSerialTMC = 2; // USART or UART used to control and monitor the smart drivers + +#ifndef RTOS const uint32_t NvicPrioritySystick = 3; // systick kicks the watchdog and starts the ADC conversions, so must be quite high +#endif + const uint32_t NvicPriorityPins = 4; // priority for GPIO pin interrupts - filament sensors must be higher than step -const uint32_t NvicPriorityStep = 5; // step interrupt is next highest, it can preempt most other interrupts -const uint32_t NvicPriorityWiFiUart = 6; // UART used to receive debug data from the WiFi module -const uint32_t NvicPriorityUSB = 6; // USB interrupt -const uint32_t NvicPriorityHSMCI = 6; // HSMCI command complete interrupt + +// Currently we set configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY in FreeRTOS to 5. +// This means that only interrupts with priority numerically at least 5 can make ISR-safe calls to FreeRTOS in an ISR. + +const uint32_t NvicPriorityStep = 6; // step interrupt is next highest, it can preempt most other interrupts +const uint32_t NvicPriorityWiFiUart = 7; // UART used to receive debug data from the WiFi module +const uint32_t NvicPriorityUSB = 7; // USB interrupt +const uint32_t NvicPriorityHSMCI = 7; // HSMCI command complete interrupt #if HAS_LWIP_NETWORKING -const uint32_t NvicPriorityNetworkTick = 7; // priority for network tick interrupt -const uint32_t NvicPriorityEthernet = 7; // priority for Ethernet interface +const uint32_t NvicPriorityNetworkTick = 8; // priority for network tick interrupt +const uint32_t NvicPriorityEthernet = 8; // priority for Ethernet interface #endif -const uint32_t NvicPrioritySpi = 7; // SPI is used for network transfers on Duet WiFi/Duet vEthernet -const uint32_t NvicPriorityTwi = 8; // TWI is used to read endstop and other inputs on the DueXn +const uint32_t NvicPrioritySpi = 8; // SPI is used for network transfers on Duet WiFi/Duet vEthernet +const uint32_t NvicPriorityTwi = 9; // TWI is used to read endstop and other inputs on the DueXn #endif diff --git a/src/SoftTimer.cpp b/src/SoftTimer.cpp index 8b0a5d77..95440e11 100644 --- a/src/SoftTimer.cpp +++ b/src/SoftTimer.cpp @@ -7,7 +7,6 @@ #include "SoftTimer.h" #include "Platform.h" -#include "Movement/DDA.h" SoftTimer * volatile SoftTimer::pendingList = nullptr; @@ -74,7 +73,7 @@ void SoftTimer::CancelCallback() // Get the tick rate /*static*/ SoftTimer::Ticks SoftTimer::GetTickRate() { - return DDA::stepClockRate; // the software timer uses the same counter as the step timer + return StepClockRate; // the software timer uses the same counter as the step timer } // ISR called from Platform. May sometimes get called prematurely. diff --git a/src/Storage/FileInfoParser.cpp b/src/Storage/FileInfoParser.cpp index f7872d62..4dfc90cf 100644 --- a/src/Storage/FileInfoParser.cpp +++ b/src/Storage/FileInfoParser.cpp @@ -346,6 +346,7 @@ bool FileInfoParser::GetFileInfo(const char *directory, const char *fileName, GC default: // should not get here parsedFileInfo.incomplete = false; + fileBeingParsed->Close(); info = parsedFileInfo; parseState = notParsing; return true; @@ -356,6 +357,7 @@ bool FileInfoParser::GetFileInfo(const char *directory, const char *fileName, GC if (quitEarly) { info = parsedFileInfo; // note that the 'incomplete' flag is still set + fileBeingParsed->Close(); parseState = notParsing; return true; } diff --git a/src/Storage/FileStore.cpp b/src/Storage/FileStore.cpp index 94b34a48..b46a68a2 100644 --- a/src/Storage/FileStore.cpp +++ b/src/Storage/FileStore.cpp @@ -5,6 +5,7 @@ #include "MassStorage.h" #include "Platform.h" #include "RepRap.h" +#include "Movement/DDA.h" uint32_t FileStore::longestWriteTime = 0; @@ -15,8 +16,7 @@ FileStore::FileStore() : writeBuffer(nullptr) void FileStore::Init() { - inUse = false; - writing = false; + usageMode = FileUseMode::free; openCount = 0; closeRequested = false; } @@ -38,8 +38,8 @@ bool FileStore::Invalidate(const FATFS *fs, bool doClose) reprap.GetPlatform().GetMassStorage()->ReleaseWriteBuffer(writeBuffer); writeBuffer = nullptr; } - Init(); } + usageMode = FileUseMode::invalidated; return true; } return false; @@ -57,7 +57,7 @@ bool FileStore::Open(const char* directory, const char* fileName, OpenMode mode) { String<MaxFilenameLength> location; MassStorage::CombineName(location.GetRef(), directory, fileName); - writing = (mode == OpenMode::write || mode == OpenMode::append); + const bool writing = (mode == OpenMode::write || mode == OpenMode::append); if (writing) { @@ -108,71 +108,91 @@ bool FileStore::Open(const char* directory, const char* fileName, OpenMode mode) return false; } crc.Reset(); - inUse = true; + usageMode = (writing) ? FileUseMode::readWrite : FileUseMode::readOnly; openCount = 1; return true; } void FileStore::Duplicate() { - if (!inUse) + switch (usageMode) { + case FileUseMode::free: INTERNAL_ERROR; - } - else - { - irqflags_t flags = cpu_irq_save(); - ++openCount; - cpu_irq_restore(flags); + break; + + case FileUseMode::readOnly: + case FileUseMode::readWrite: + { + const irqflags_t flags = cpu_irq_save(); + ++openCount; + cpu_irq_restore(flags); + } + break; + + case FileUseMode::invalidated: + default: + break; } } // This may be called from an ISR, in which case we need to defer the close bool FileStore::Close() { - if (inInterrupt()) + switch (usageMode) { - if (!inUse) + case FileUseMode::free: + if (!inInterrupt()) { - return false; + INTERNAL_ERROR; } + return false; - const irqflags_t flags = cpu_irq_save(); - if (openCount > 1) + case FileUseMode::readOnly: + case FileUseMode::readWrite: { - --openCount; + const irqflags_t flags = cpu_irq_save(); + if (openCount > 1) + { + --openCount; + cpu_irq_restore(flags); + return true; + } + else if (inInterrupt()) + { + closeRequested = true; + cpu_irq_restore(flags); + return true; + } + else + { + cpu_irq_restore(flags); + return ForceClose(); + } } - else + + case FileUseMode::invalidated: + default: { - closeRequested = true; + const irqflags_t flags = cpu_irq_save(); + if (openCount > 1) + { + --openCount; + } + else + { + usageMode = FileUseMode::free; + } + cpu_irq_restore(flags); + return true; } - cpu_irq_restore(flags); - return true; } - - if (!inUse) - { - INTERNAL_ERROR; - return false; - } - - const irqflags_t flags = cpu_irq_save(); - --openCount; - bool leaveOpen = (openCount != 0); - cpu_irq_restore(flags); - - if (leaveOpen) - { - return true; - } - - return ForceClose(); } bool FileStore::ForceClose() { bool ok = true; - if (writing) + if (usageMode == FileUseMode::readWrite) { ok = Flush(); } @@ -184,8 +204,7 @@ bool FileStore::ForceClose() } const FRESULT fr = f_close(&file); - inUse = false; - writing = false; + usageMode = FileUseMode::free; closeRequested = false; openCount = 0; return ok && fr == FR_OK; @@ -193,23 +212,30 @@ bool FileStore::ForceClose() bool FileStore::Seek(FilePosition pos) { - if (!inUse) + switch (usageMode) { + case FileUseMode::free: INTERNAL_ERROR; return false; + + case FileUseMode::readOnly: + case FileUseMode::readWrite: + return f_lseek(&file, pos) == FR_OK; + + case FileUseMode::invalidated: + default: + return false; } - FRESULT fr = f_lseek(&file, pos); - return fr == FR_OK; } FilePosition FileStore::Position() const { - return (inUse) ? file.fptr : 0; + return (usageMode == FileUseMode::readOnly || usageMode == FileUseMode::readWrite) ? file.fptr : 0; } uint32_t FileStore::ClusterSize() const { - return (inUse) ? file.fs->csize * 512u : 1; // we divide by the cluster size so return 1 not 0 if there is an error + return (usageMode == FileUseMode::readOnly || usageMode == FileUseMode::readWrite) ? file.fs->csize * 512u : 1; // we divide by the cluster size so return 1 not 0 if there is an error } #if 0 // not currently used @@ -221,13 +247,22 @@ bool FileStore::GoToEnd() FilePosition FileStore::Length() const { - if (!inUse) + switch (usageMode) { + case FileUseMode::free: INTERNAL_ERROR; return 0; - } - return (writeBuffer != nullptr) ? file.fsize + writeBuffer->BytesStored() : file.fsize; + case FileUseMode::readOnly: + return file.fsize; + + case FileUseMode::readWrite: + return (writeBuffer != nullptr) ? file.fsize + writeBuffer->BytesStored() : file.fsize; + + case FileUseMode::invalidated: + default: + return 0; + } } // Single character read @@ -239,20 +274,29 @@ bool FileStore::Read(char& b) // Returns the number of bytes read or -1 if the read process failed int FileStore::Read(char* extBuf, size_t nBytes) { - if (!inUse) + switch (usageMode) { + case FileUseMode::free: INTERNAL_ERROR; return -1; - } - UINT bytes_read; - FRESULT readStatus = f_read(&file, extBuf, nBytes, &bytes_read); - if (readStatus != FR_OK) - { - reprap.GetPlatform().Message(ErrorMessage, "Cannot read file.\n"); + case FileUseMode::readOnly: + case FileUseMode::readWrite: + { + UINT bytes_read; + FRESULT readStatus = f_read(&file, extBuf, nBytes, &bytes_read); + if (readStatus != FR_OK) + { + reprap.GetPlatform().Message(ErrorMessage, "Cannot read file.\n"); + return -1; + } + return (int)bytes_read; + } + + case FileUseMode::invalidated: + default: return -1; } - return (int)bytes_read; } // As Read but stop after '\n' or '\r\n' and null-terminate the string. @@ -291,10 +335,10 @@ int FileStore::ReadLine(char* buf, size_t nBytes) FRESULT FileStore::Store(const char *s, size_t len, size_t *bytesWritten) { - uint32_t time = micros(); + uint32_t time = Platform::GetInterruptClocks(); crc.Update(s, len); - FRESULT writeStatus = f_write(&file, s, len, bytesWritten); - time = micros() - time; + const FRESULT writeStatus = f_write(&file, s, len, bytesWritten); + time = Platform::GetInterruptClocks() - time; if (time > longestWriteTime) { longestWriteTime = time; @@ -314,97 +358,121 @@ bool FileStore::Write(const char* b) bool FileStore::Write(const char *s, size_t len) { - if (!inUse) + switch (usageMode) { + case FileUseMode::free: INTERNAL_ERROR; return false; - } - size_t totalBytesWritten = 0; - FRESULT writeStatus = FR_OK; - if (writeBuffer == nullptr) - { - writeStatus = Store(s, len, &totalBytesWritten); - } - else - { - do + case FileUseMode::readOnly: + case FileUseMode::readWrite: { - size_t bytesStored = writeBuffer->Store(s + totalBytesWritten, len - totalBytesWritten); - if (writeBuffer->BytesLeft() == 0) + size_t totalBytesWritten = 0; + FRESULT writeStatus = FR_OK; + if (writeBuffer == nullptr) { - const size_t bytesToWrite = writeBuffer->BytesStored(); - size_t bytesWritten; - writeStatus = Store(writeBuffer->Data(), bytesToWrite, &bytesWritten); - writeBuffer->DataTaken(); - - if (bytesToWrite != bytesWritten) + writeStatus = Store(s, len, &totalBytesWritten); + } + else + { + do { - // Something went wrong - break; + size_t bytesStored = writeBuffer->Store(s + totalBytesWritten, len - totalBytesWritten); + if (writeBuffer->BytesLeft() == 0) + { + const size_t bytesToWrite = writeBuffer->BytesStored(); + size_t bytesWritten; + writeStatus = Store(writeBuffer->Data(), bytesToWrite, &bytesWritten); + writeBuffer->DataTaken(); + + if (bytesToWrite != bytesWritten) + { + // Something went wrong + break; + } + } + totalBytesWritten += bytesStored; } + while (writeStatus == FR_OK && totalBytesWritten != len); + } + + if ((writeStatus != FR_OK) || (totalBytesWritten != len)) + { + reprap.GetPlatform().Message(ErrorMessage, "Failed to write to file. Drive may be full.\n"); + return false; } - totalBytesWritten += bytesStored; + return true; } - while (writeStatus == FR_OK && totalBytesWritten != len); - } - if ((writeStatus != FR_OK) || (totalBytesWritten != len)) - { - reprap.GetPlatform().Message(ErrorMessage, "Failed to write to file. Drive may be full.\n"); - return false; + case FileUseMode::invalidated: + default: + return 0; } - return true; } bool FileStore::Flush() { - if (!inUse) + switch (usageMode) { + case FileUseMode::free: INTERNAL_ERROR; return false; - } - if (writeBuffer != nullptr) - { - const size_t bytesToWrite = writeBuffer->BytesStored(); - if (bytesToWrite != 0) - { - size_t bytesWritten; - const FRESULT writeStatus = Store(writeBuffer->Data(), bytesToWrite, &bytesWritten); - writeBuffer->DataTaken(); + case FileUseMode::readOnly: + return true; - if ((writeStatus != FR_OK) || (bytesToWrite != bytesWritten)) + case FileUseMode::readWrite: + if (writeBuffer != nullptr) + { + const size_t bytesToWrite = writeBuffer->BytesStored(); + if (bytesToWrite != 0) { - reprap.GetPlatform().Message(ErrorMessage, "Failed to write to file. Drive may be full.\n"); - return false; + size_t bytesWritten; + const FRESULT writeStatus = Store(writeBuffer->Data(), bytesToWrite, &bytesWritten); + writeBuffer->DataTaken(); + + if ((writeStatus != FR_OK) || (bytesToWrite != bytesWritten)) + { + reprap.GetPlatform().Message(ErrorMessage, "Failed to write to file. Drive may be full.\n"); + return false; + } } } - } + return f_sync(&file) == FR_OK; - return f_sync(&file) == FR_OK; + case FileUseMode::invalidated: + default: + return false; + } } // Truncate file at current file pointer bool FileStore::Truncate() { - if (!inUse) + switch (usageMode) { + case FileUseMode::free: + case FileUseMode::readOnly: INTERNAL_ERROR; return false; - } - if (!Flush()) - { + case FileUseMode::readWrite: + if (!Flush()) + { + return false; + } + return f_truncate(&file) == FR_OK; + + case FileUseMode::invalidated: + default: return false; } - - return f_truncate(&file) == FR_OK; } +// Return the file write time in milliseconds, and clear it float FileStore::GetAndClearLongestWriteTime() { - float ret = (float)longestWriteTime/1000.0; + const float ret = (float)longestWriteTime * StepClocksToMillis; longestWriteTime = 0; return ret; } @@ -415,16 +483,25 @@ float FileStore::GetAndClearLongestWriteTime() // The first element of the table must be set to the total number of 32-bit entries in the table before calling this. bool FileStore::SetClusterMap(uint32_t tbl[]) { - if (!inUse) + switch (usageMode) { + case FileUseMode::free: INTERNAL_ERROR; return false; - } - file.cltbl = tbl; - FRESULT ret = f_lseek(&file, CREATE_LINKMAP); -// debugPrintf("ret %d need %u\n", (int)ret, tbl[0]); - return ret == FR_OK; + case FileUseMode::readOnly: + case FileUseMode::readWrite: + { + file.cltbl = tbl; + const FRESULT ret = f_lseek(&file, CREATE_LINKMAP); +// debugPrintf("ret %d need %u\n", (int)ret, tbl[0]); + return ret == FR_OK; + } + + case FileUseMode::invalidated: + default: + return false; + } } #endif diff --git a/src/Storage/FileStore.h b/src/Storage/FileStore.h index dbaf200f..9f674a4b 100644 --- a/src/Storage/FileStore.h +++ b/src/Storage/FileStore.h @@ -17,6 +17,14 @@ enum class OpenMode : uint8_t append // append to an existing file, or create a new file if it is not found }; +enum class FileUseMode : uint8_t +{ + free, // file object is free + readOnly, // file object is in use for reading only + readWrite, // file object is in use for reading and writing + invalidated // file object is in use but file system has been invalidated +}; + class FileStore { public: @@ -63,9 +71,8 @@ private: FileWriteBuffer *writeBuffer; volatile unsigned int openCount; volatile bool closeRequested; + FileUseMode usageMode; - bool inUse; - bool writing; CRC32 crc; static uint32_t longestWriteTime; diff --git a/src/Storage/MassStorage.cpp b/src/Storage/MassStorage.cpp index 91c3e17d..a42c4281 100644 --- a/src/Storage/MassStorage.cpp +++ b/src/Storage/MassStorage.cpp @@ -126,17 +126,9 @@ FileStore* MassStorage::OpenFile(const char* directory, const char* fileName, Op MutexLocker lock(fsMutex); for (size_t i = 0; i < MAX_FILES; i++) { - if (!files[i].inUse) + if (files[i].usageMode == FileUseMode::free) { - if (files[i].Open(directory, fileName, mode)) - { - files[i].inUse = true; - return &files[i]; - } - else - { - return nullptr; - } + return (files[i].Open(directory, fileName, mode)) ? &files[i]: nullptr; } } } @@ -150,7 +142,7 @@ void MassStorage::CloseAllFiles() MutexLocker lock(fsMutex); for (FileStore& f : files) { - while (f.inUse) + while (f.usageMode != FileUseMode::free) { f.Close(); } @@ -595,7 +587,7 @@ bool MassStorage::AnyFileOpen(const FATFS *fs) const return false; } -// Invalidate all open files on the specified file system, returning true if any files were invalidated +// Invalidate all open files on the specified file system, returning the number of files that were invalidated unsigned int MassStorage::InvalidateFiles(const FATFS *fs, bool doClose) { unsigned int invalidated = 0; @@ -630,13 +622,13 @@ bool MassStorage::IsCardDetected(size_t card) const return info[card].cardState == CardDetectState::present; } -// Unmount a file system returning true if any pen files were invalidated -bool MassStorage::InternalUnmount(size_t card, bool doClose) +// Unmount a file system returning true if any open files were invalidated +unsigned int MassStorage::InternalUnmount(size_t card, bool doClose) { SdCardInfo& inf = info[card]; MutexLocker lock1(fsMutex); MutexLocker lock2(inf.volMutex); - const bool invalidated = InvalidateFiles(&inf.fileSystem, doClose); + const unsigned int invalidated = InvalidateFiles(&inf.fileSystem, doClose); f_mount(card, nullptr); memset(&inf.fileSystem, 0, sizeof(inf.fileSystem)); sd_mmc_unmount(card); @@ -650,7 +642,7 @@ unsigned int MassStorage::GetNumFreeFiles() const MutexLocker lock(fsMutex); for (const FileStore & fil : files) { - if (!fil.inUse) + if (fil.usageMode == FileUseMode::free) { ++numFreeFiles; } diff --git a/src/Storage/MassStorage.h b/src/Storage/MassStorage.h index a67f103c..ab42896f 100644 --- a/src/Storage/MassStorage.h +++ b/src/Storage/MassStorage.h @@ -96,7 +96,7 @@ private: CardDetectState cardState; }; - bool InternalUnmount(size_t card, bool doClose); + unsigned int InternalUnmount(size_t card, bool doClose); static time_t ConvertTimeStamp(uint16_t fdate, uint16_t ftime); SdCardInfo info[NumSdCards]; diff --git a/src/Version.h b/src/Version.h index 567bb215..ebacee61 100644 --- a/src/Version.h +++ b/src/Version.h @@ -18,11 +18,11 @@ # define RTOSVER #endif -# define VERSION MAIN_VERSION RTOSVER "RC5" +# define VERSION MAIN_VERSION RTOSVER "RC6" #endif #ifndef DATE -# define DATE "2018-05-23b1" +# define DATE "2018-05-30b1" #endif #define AUTHORS "reprappro, dc42, chrishamm, t3p3, dnewman" |